英文:
Is there some sort of constructor being generated here?
问题
在其中一个排序示例中,他们使用了以下代码:
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 根据 Age 字段为 []Person 实现 sort.Interface 接口。
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)
}
对于我来说,带有 Sort 的那一行有点令人困惑:
sort.Sort(ByAge(people))
ByAge(people) 是否生成了某种构造函数来复制传入的数组?我不确定我理解新类型 ByAge 如何访问元素。
英文:
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.
答案1
得分: 5
语法foo(expr)
中,foo
是一个类型,expr
是一个类型转换,如规范中所述:
转换
转换是形式为
T(x)
的表达式,其中T
是一个类型,x
是一个可以转换为类型T
的表达式。转换 = 类型 "(" 表达式 [ "," ] ")" .如果类型以运算符
*
或<-
开头,或者类型以关键字func
开头且没有结果列表,则必要时必须使用括号来避免歧义:*Point(p) // 与*(Point(p))相同 (*Point)(p) // 将p转换为*Point <-chan int(c) // 与<-(chan int(c))相同 (<-chan int)(c) // 将c转换为<-chan int func()(x) // 函数签名func() x (func())(x) // 将x转换为func() (func() int)(x) // 将x转换为func() int func() int(x) // 将x转换为func() int(无歧义)
在以下情况下,常量值
x
可以在任何情况下转换为类型T
:
x
可以由类型T
的值表示。x
是浮点常量,T
是浮点类型,并且使用IEEE 754舍入到最近偶数规则将x
舍入后,x
可以由类型T
的值表示。常量T(x)
是舍入后的值。x
是整数常量,T
是字符串类型。在这种情况下,适用于非常量x
的相同规则。转换常量会产生一个类型化的常量作为结果。
uint(iota) // 类型为uint的iota值 float32(2.718281828) // 类型为float32的2.718281828 complex128(1) // 类型为complex128的1.0 + 0.0i float32(0.49999999) // 类型为float32的0.5 string('x') // 类型为string的"x" string(0x266c) // 类型为string的"♬" MyString("foo" + "bar") // 类型为MyString的"foobar" string([]byte{'a'}) // 非常量:[]byte{'a'}不是常量 (*int)(nil) // 非常量:nil不是常量,*int不是布尔、数值或字符串类型 int(1.2) // 非法:1.2不能表示为int string(65.0) // 非法:65.0不是整数常量
在以下情况下,非常量值
x
可以在任何情况下转换为类型T
:
x
可以赋值给T
。x
的类型和T
具有相同的基础类型。x
的类型和T
都是未命名的指针类型,它们的指针基础类型具有相同的基础类型。x
的类型和T
都是整数或浮点类型。x
的类型和T
都是复数类型。x
是整数或字节或符文的切片,T
是字符串类型。x
是字符串,T
是字节或符文的切片。对于(非常量)数值类型之间或与字符串类型之间的转换,有特定的规则。这些转换可能会改变
x
的表示并产生运行时成本。所有其他转换只会改变类型而不会改变x
的表示。没有语言机制可以在指针和整数之间进行转换。包
unsafe
在受限制的情况下实现了此功能。
有关更多详细信息,请参见链接页面。
英文:
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)
where T
is a type and x
> is an expression that can be converted to type T
.
> <pre>
> Conversion = Type "(" Expression [ "," ] ")" .
> </pre>
> If the type starts with
> the operator *
or <-
, or if the type starts with the keyword func
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 type T
in any of these cases:
>
> * x
is representable by a value of type T
.
> * x
is a floating-point constant, T
is a floating-point type, and x
is representable by a value of type T
after rounding using IEEE 754 round-to-even rules. The constant T(x)
is the rounded value.
> * x
is an integer constant and T
is a string type. The same rule as for non-constant x
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 to T
.
> * x
's type and T
have identical underlying types.
> * x
's type and T
are unnamed pointer types and their pointer base types
> have identical underlying types.
> * x
's type and T
are both integer or floating point types. x
's type and T
are both complex types.
> * x
is an integer or a slice of bytes or runes and T
is a string type.
> * x
is a string and T
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 of x
.
>
> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论