这里是否生成了某种构造函数?

huangapple go评论81阅读模式
英文:

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 (
	&quot;fmt&quot;
	&quot;sort&quot;
)

type Person struct {
	Name string
	Age  int
}

func (p Person) String() string {
	return fmt.Sprintf(&quot;%s: %d&quot;, 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 &lt; a[j].Age }

func main() {
	people := []Person{
		{&quot;Bob&quot;, 31},
		{&quot;John&quot;, 42},
		{&quot;Michael&quot;, 17},
		{&quot;Jenny&quot;, 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 &lt;-, 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 Thave 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.

huangapple
  • 本文由 发表于 2014年12月13日 04:51:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/27451908.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定