go Type Identical &Value Assignability & Type Conversions

来源:互联网 发布:oracle数据触发器 编辑:程序博客网 时间:2024/06/06 07:43

 

 

1. Type identity

Two types are either identical or different.

Two named types are identical if their type names originate in the same TypeSpec. A named and an unnamed type are always different. Two unnamed types are identical if the corresponding type literals are identical, that is, if they have the same literal structure and corresponding components have identical types. In detail:

· Two array types are identical if they have identical element types and the same array length.

· Two slice types are identical if they have identical element types.

· Two struct types are identical if they have the same sequence of fields, and if corresponding fields have the same names, and identical types, and identical tags. Two anonymous fields are considered to have the same name. Lower-case field names from different packages are always different.

· Two pointer types are identical if they have identical base types.

· Two function types are identical if they have the same number of parameters and result values, corresponding parameter and result types are identical, and either both functions are variadic or neither is. Parameter and result names are not required to match.

· Two interface types are identical if they have the same set of methods with the same names and identical function types. Lower-case method names from different packages are always different. The order of the methods is irrelevant.

· Two map types are identical if they have identical key and value types.

· Two channel types are identical if they have identical value types and the same direction.

Given the declarations

type (

    T0 []string

    T1 []string

    T2 struct{ a, b int }

    T3 struct{ a, c int }

    T4 func(int, float64) *T0

    T5 func(x int, y float64) *[]string

)

 

these types are identical:

T0 and T0

[]int and []int

struct{ a, b *T5 } and struct{ a, b *T5 }

func(x int, y float64) *[]string and func(int, float64) (result *[]string)

 

T0 and T1 are different because they are named types with distinct declarations; func(int, float64) *T0 and func(x int, y float64) *[]string are different because T0 is different from []string.

2. Assignability

A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:

· x's type is identical to T.

· x's type V and T have identical underlying types and at least one of V or T is not a named type.

· T is an interface type and x implements T.

· x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type.

· x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.

· x is an untyped constant representable by a value of type T.

 

3. 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.

Conversion = Type "(" Expression [ "," ] ")" .

 

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)

 

constant value x can be converted to type T in any of these cases:

常量字面量复制给类型T变量主要涉及到的就是 数字常量字面量

· 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, but with an IEEE -0.0 further rounded to an unsigned 0.0. 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

float64(-1e-1000)        // 0.0 of type float64

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. Theseconversions 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.

Conversions between numeric types

For the conversion of non-constant numeric values, the following rules apply:

When converting between integer types, if the value is a signed integer, it is sign extended to implicit infinite precision; otherwise it is zero extended. It is then truncated to fit in the result type's size. For example, if v := uint16(0x10F0), then uint32(int8(v)) == 0xFFFFFFF0. The conversion always yields a valid value; there is no indication of overflow.

When converting a floating-point number to an integer, the fraction is discarded (truncation towards zero).

When converting an integer or floating-point number to a floating-point type, or a complex number to another complex type, the result value is rounded to the precision specified by the destination type. For instance, the value of a variable x of type float32 may be stored using additional precision beyond that of an IEEE-754 32-bit number, but float32(x) represents the result of rounding x's value to 32-bit precision. Similarly, x + 0.1 may use more than 32 bits of precision, but float32(x + 0.1) does not.

In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent.

Conversions to and from a string type

 主要涉及 string 和 []byte[] rune 转换

Converting a signed or unsigned integer value to a string type yields a string containing the UTF-8 representation of the integer. Values outside the range of valid Unicode code points are converted to "\uFFFD".

整形转换为字符串,将整形数值看作Unicode 码进行转译,如果该整数代表的数值不能转换为Unicode码,则直接转为\ufffd

string('a')       // "a"

string(-1)        // "\ufffd" == "\xef\xbf\xbd"

string(0xf8)      // "\u00f8" == "ø" == "\xc3\xb8"

type MyString string

MyString(0x65e5)  // "\u65e5" == "" == "\xe6\x97\xa5"

 

Converting a slice of bytes to a string type yields a string whose successive bytes are the elements of the slice.

[]byte转换为string 就是该slice每个字节所代表的字符构成的字符串

string([]byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'})   // "hellø"

string([]byte{})                                     // ""

string([]byte(nil))                                  // ""

 

type MyBytes []byte

string(MyBytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'})  // "hellø"

 

Converting a slice of runes to a string type yields a string that is the concatenation of the individual rune values converted to strings.

[]rune 转换为string ,会进行译码,将rune存放的unicode编码转换为具体的字符值

string([]rune{0x767d, 0x9d6c, 0x7fd4})   // "\u767d\u9d6c\u7fd4" == "白鵬翔"

string([]rune{})                         // ""

string([]rune(nil))                      // ""

 

type MyRunes []rune

string(MyRunes{0x767d, 0x9d6c, 0x7fd4})  // "\u767d\u9d6c\u7fd4" == "白鵬翔"

 

Converting a value of a string type to a slice of bytes type yields a slice whose successive elements are the bytes of the string.

String 转 []byte 直接将字符串的每个字符存入[]byte 每个字节中

[]byte("hellø")   // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}

[]byte("")        // []byte{}

 

MyBytes("hellø")  // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}

 

Converting a value of a string type to a slice of runes type yields a slice containing the individual Unicode code points of the string.

String 转 []rune 会将string每个字符的unicode码存入[]rune

[]rune(MyString("白鵬翔"))  // []rune{0x767d, 0x9d6c, 0x7fd4}

[]rune("")                 // []rune{}

 

MyRunes("白鵬翔")           // []rune{0x767d, 0x9d6c, 0x7fd4}

 

 

 

 

0 0
原创粉丝点击