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 rename types in this way is to make your source code clearer.
Another reason is that you can define methods on a type Score
, but you
cannot define methods on a basic type such as int
.
This sort of assignment is permitted:
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.
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 might represent a 2-dimensional point:
type Point struct {
x, y int
}
One way to create a new struct is to use the new
function like this:
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 written 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.