In one of the sorting examples, they use the following code:
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}
// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
people := []Person{
{"Bob", 31},
{"John", 42},
{"Michael", 17},
{"Jenny", 26},
}
fmt.Println(people)
sort.Sort(ByAge(people))
fmt.Println(people)
}
The line with the Sort is a bit confusing for me:
sort.Sort(ByAge(people))
Does ByAge(people) generate some kind of constructor that copies the array being passed in? I'm not sure I understand how the new type, ByAge, has access to the elements otherwise.
The syntax foo(expr)
where foo
is a type and expr
is a type conversion, as described in the spec:
Conversions
Conversions are expressions of the form
T(x)
whereT
is a type andx
is an expression that can be converted to typeT
.Conversion = Type "(" Expression [ "," ] ")" .If the type starts with the operator
*
or<-
, or if the type starts with the keywordfunc
and has no result list, it must be parenthesized when necessary to avoid ambiguity:*Point(p) // same as *(Point(p)) (*Point)(p) // p is converted to *Point <-chan int(c) // same as <-(chan int(c)) (<-chan int)(c) // c is converted to <-chan int func()(x) // function signature func() x (func())(x) // x is converted to func() (func() int)(x) // x is converted to func() int func() int(x) // x is converted to func() int (unambiguous)
A constant value
x
can be converted to typeT
in any of these cases:
x
is representable by a value of typeT
.x
is a floating-point constant,T
is a floating-point type, andx
is representable by a value of typeT
after rounding using IEEE 754 round-to-even rules. The constantT(x)
is the rounded value.x
is an integer constant andT
is a string type. The same rule as for non-constantx
applies in this case.Converting a constant yields a typed constant as result.
uint(iota) // iota value of type uint float32(2.718281828) // 2.718281828 of type float32 complex128(1) // 1.0 + 0.0i of type complex128 float32(0.49999999) // 0.5 of type float32 string('x') // "x" of type string string(0x266c) // "♬" of type string MyString("foo" + "bar") // "foobar" of type MyString string([]byte{'a'}) // not a constant: []byte{'a'} is not a constant (*int)(nil) // not a constant: nil is not a constant, *int is not a boolean, numeric, or string type int(1.2) // illegal: 1.2 cannot be represented as an int string(65.0) // illegal: 65.0 is not an integer constant
A non-constant value x can be converted to type T in any of these cases:
x
is assignable toT
.x
's type andT
have identical underlying types.x
's type andT
are unnamed pointer types and their pointer base types have identical underlying types.x
's type andT
are both integer or floating point types.x
's type andT
are both complex types.x
is an integer or a slice of bytes or runes andT
is a string type.x
is a string andT
is a slice of bytes or runes.Specific rules apply to (non-constant) conversions between numeric types or to and from a string type. These conversions may change the representation of
x
and incur a run-time cost. All other conversions only change the type but not the representation ofx
.There is no linguistic mechanism to convert between pointers and integers. The package unsafe implements this functionality under restricted circumstances.
See the linked page for more details.