Types and Structures¶
New Types¶
You can create your own types in Go using the type
keyword. For example:
type Score int
func show(s Score) {
fmt.Println("mark =", s)
}
func main() {
s := Score(5) // s is declared to be of type Score
show(s)
}
In this example, int
is said to be the underlying type of Score
.
One reason to create types is to make your source code clearer. Another reason
is that you can define methods on the type Score
, but you cannot define
methods on a basic type such as int
.
You can call show
like this:
show(5)
Strictly speaking, 5 is an int
, and so it is not of type Score
.
However, because Score
has an underlying type of int
, this statement
is not an error in Go.
Here is an example where you do get a type error. Suppose we add a new type
called Mark
:
type Mark int
And then call this code:
m := Mark(3)
show(m) // compiler error: m is wrong type
This doesn’t compile because m
is of type Mark
, but show
expects a
parameter of type Score
. Even though both Mark
and Score
have the
same underlying type, one cannot be assigned to the other.
See the Go specification for the exact type equivalence rules.
Structures¶
Go structs are similar to the structures in C-like languages. For example, here is how you can represent a 2-dimensional point:
type Point struct {
x, y int
}
One way to create a struct is to use the new
function:
p := new(Point) // new initializes p.x and p.y to their zero values
fmt.Println("p.x: ", p.x)
fmt.Println("p.y: ", p.y)
The new
function always sets the variables in a struct to their zero
values. If you want to initialize them to some other values, you can use a
composite literal like this:
dest := Point{-8, 11} // Point{-8, 11} is a composite literal
fmt.Println("dest.x: ", dest.x)
fmt.Println("dest.y: ", dest.y)
Note that new
is not used here.
Here is an example of a struct built from two points:
type Segment struct {
start, end Point
}
You can create a new Segment
using a composite literal like this:
trip := Segment{Point{1, 2}, Point{3, 4}}
fmt.Printf("%v\n", trip) // %v prints Go values in a nicely formatted way
This prints:
{{1 2} {3 4}}
Another way to write a composite literal is with explicit parameter names:
trip := Segment{start: Point{1, 2}, end: Point{3, 4}}
When explicit names are given like this, the order of the parameters doesn’t matter. The above declaration is the same as this:
trip := Segment{end: Point{3, 4}, start: Point{1, 2}} // order doesn't matter
// when you provide
// names
Named composite literals are especially useful for longer, more complex structs where the order of parameters can be hard to remember.
Questions¶
- Explain the idea of an underlying type.
- Show how to define a new Go type called
Name
whose underlying type isstring
. - When you create a struct value using
new
, what values are assigned to the variables in the struct? - Show how to define a new Go struct called
Person
that contains the name of a person, and their age. Then write code that does the following:- Uses
new
to create a newPerson
whose name is Ray and whose age is 19. - Uses a composite literal to create a new
Person
whose name is Ann and whose age is 25. - Uses a composite literal with explicit parameter names to create a new person whose name is Pat and whose age is 30.
- Uses