Go addressable detailed

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

The Go Language specification defines the definition of an addressable (addressable) object,

For the operand x of type T, the address operation &x generates a pointer of type *t to X. The operand must be addressable, which is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, X is also be a (possibly parenthesized) composite literal. If the evaluation of X would cause a run-time panic, then the evaluation of &X does too.

For an object x , if its type is T , then &x a pointer to the type is generated, *T x which is the first sentence of this paragraph, and is one of the ways we often use to get object pointers during development.

Addressable

This paragraph of the above specification x must be addressable, that is to say, it can only be a few ways:

    • A variable:&x
    • Pointer reference (pointer indirection):&*x
    • Slice index operations (regardless of whether slice is addressable):&s[1]
    • Fields that can address a struct:&point.X
    • An indexed operation for an addressable array:&a[0]
    • Composite literal type:&struct{ X int }{1}

The following conditions x are not addressable and you cannot use the &x get pointer:

    • Bytes in the string:
    • Elements in a Map object
    • Dynamic value of interface object (obtained by type assertions)
    • Constant
    • Literal value (non-composite literal)
    • Package-level functions
    • Method methods (used as function values)
    • Median value (intermediate value):
      • Function call
      • An explicit type conversion
      • Various types of operations (except pointers refer to pointer dereference operations *x ):
        • Channel receive operations
        • Sub-string operations
        • Sub-slice operations
        • Operators such as subtraction

Tapir Games in his article unaddressable-values did a good job of finishing.

There are several points to explain below:

    • Why can't a constant be addressed?: If it can be addressed, we can modify the value of the constant by the pointer, breaking the definition of the constant.
    • Why can't the elements of map be addressable? : Two reasons, if the object does not exist, then return 0 value, 0 value is immutable object, so can not address, if the object exists, because the address of the map implementation in Go is changed, which means that the result of addressing is meaningless.
    • Why is the element read addressable by slice regardless of whether it is addressable? : Because the slice implements an array, it can be addressed.
    • Why the characters/bytes in a string cannot be addressed: Because the string is immutable.

There are several other references in the specification addressable :

    • When invoking a method with receiver as a pointer type, using a addressable value will automatically get a pointer to that value
    • ++, -- the Action object of the statement must be addressable or the index operation of the map
    • =the left object of an assignment statement must be addressable, or the index operation of the map, or_
    • The same statement is used on the previous bar for ... range

reflect.ValueCanAddrmethods and CanSet methods of

When we use to reflect perform some of the underlying operations, such as writing serialization libraries, RPC framework development, codec, plug-in development and other services, often used reflect.Value in the method used to dynamically assign values to the CanSet object. CanSet CanAddr There is only one limitation, that is, the field of the struct type unexported cannot Set , so this section is mainly about CanAddr .

Not reflect.Value CanAddr All methods are returned true , according to its godoc, we can know:

CANADDR reports whether the value ' s address can obtained with ADDR. Such values are called addressable. A value is addressable if it's an element of a slice, an element of a addressable array, a field of an addressable Struc T, or the result of dereferencing a pointer. If Canaddr returns false, calling Addr would panic.

That is, only the following types are reflect.Value CanAddr true , such values are addressable :

    • Elements of the Slice
    • Elements of an addressable array
    • Fields for addressable structs
    • The result of a pointer reference

And the scope of the addressable specification reflect.Value , addressable such as the allocation of variables on the stack, with the end of the life cycle of the method, the objects on the stack are recycled, if you get their address, there will be inconsistent results, and even security issues.

For stack and heap object assignment and escape analysis, you can read a series of articles written by William Kennedy: Escape analysis of the Go language mechanism

So if you want to reflect.Value update the value of it, you should make sure its CanSet method returns true so that it can be SetXXX set.

reflect.ValueSometimes it's a bit confusing to use func Indirect(v Value) Value and func (v Value) Elem() Value two methods, and sometimes they return the same value, sometimes not.

To summarize:

    1. If reflect.Value It is a pointer, it is v.Elem() equivalent toreflect.Indirect(v)
    2. If not a pointer
      2.1 If yes interface , then reflect.Indirect(v) return the same value, and v.Elem() return the dynamic value of the interface
      2.2 If it is a different value, it v.Elem() will panic and reflect.Indirect(v) return the original value

The following code lists some of the reflect.Value things that can be addressable, and you need to be aware of the case of arrays and struct fields, that is,,,, x7 x9 x14 x15 the correct way to handle it.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 66676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
 PackageMainImport("FMT""Reflect""Time")funcMain () {checkcanaddr ()}typeSstruct{XintYstringZint}funcM ()int{return -}varx0 =0funcCheckcanaddr () {//addressable situationV: = reflect. ValueOf (x0) fmt. Printf ("x0:%v \tcan be addressable and set:%t,%t\n", x0, v.canaddr (), V.canset ())//false,falsevarX1 =1v = reflect. Indirect (reflect. ValueOf (x1)) fmt. Printf ("x1:%v \tcan be addressable and set:%t,%t\n", X1, V.canaddr (), V.canset ())//false,falsevarx2 = &X1V = reflect. Indirect (reflect. ValueOf (x2)) fmt. Printf ("X2:%v \tcan be addressable and set:%t,%t\n", x2, V.canaddr (), V.canset ())//true,truevarx3 = time. Now () v = reflect. Indirect (reflect. ValueOf (x3)) FMT. Printf ("X3:%v \tcan be addressable and set:%t,%t\n", X3, V.canaddr (), V.canset ())//false,falsevarx4 = &x3v = reflect. Indirect (reflect. ValueOf (x4)) fmt. Printf ("x4:%v \tcan be addressable and set:%t,%t\n", X4, V.canaddr (), V.canset ())//True,truevarx5 = []int{1,2,3}v = reflect. ValueOf (X5) fmt. Printf ("X5:%v \tcan be addressable and set:%t,%t\n", X5, V.canaddr (), V.canset ())//False,falsevarx6 = []int{1,2,3}v = reflect. ValueOf (X6[0]) FMT. Printf ("x6:%v \tcan be addressable and set:%t,%t\n", X6[0], v.canaddr (), V.canset ())//false,falsevarX7 = []int{1,2,3}v = reflect. ValueOf (X7). Index(0) FMT. Printf ("X7:%v \tcan be addressable and set:%t,%t\n", X7[0], v.canaddr (), V.canset ())//true,truev = reflect. ValueOf (&x7[1]) FMT. Printf ("x7.1:%v \tcan be addressable and set:%t,%t\n", X7[1], v.canaddr (), V.canset ())//true,truevarx8 =[3]int{1,2,3}v = reflect. ValueOf (x8[0]) FMT. Printf ("x8:%v \tcan be addressable and set:%t,%t\n", x8[0], v.canaddr (), V.canset ())//false,false//Https://groups.google.com/forum/#!topic/golang-nuts/RF9zsX82MWwvarX9 =[3]int{1,2,3}v = reflect. Indirect (reflect. ValueOf (x9). Index(0) FMT. Printf ("x9:%v \tcan be addressable and set:%t,%t\n", x9[0], v.canaddr (), V.canset ())//false,falsevarx10 =[3]int{1,2,3}v = reflect. Indirect (reflect. ValueOf (&x10)). Index(0) FMT. Printf ("x9:%v \tcan be addressable and set:%t,%t\n", x10[0], v.canaddr (), V.canset ())//true,truevarx11 = S{}v = reflect. ValueOf (X11) fmt. Printf ("x11:%v \tcan be addressable and set:%t,%t\n", X11, V.canaddr (), V.canset ())//false,falsevarx12 = S{}v = reflect. Indirect (reflect. ValueOf (&x12)) fmt. Printf ("x12:%v \tcan be addressable and set:%t,%t\n", X12, V.canaddr (), V.canset ())//true,truevarX13 = S{}v = reflect. ValueOf (x13). Fieldbyname ("X") FMT. Printf ("x13:%v \tcan be addressable and set:%t,%t\n", X13, V.canaddr (), V.canset ())//false,falsevarx14 = S{}v = reflect. Indirect (reflect. ValueOf (&x14)). Fieldbyname ("X") FMT. Printf ("x14:%v \tcan be addressable and set:%t,%t\n", x14, V.canaddr (), V.canset ())//true,truevarx15 = S{}v = reflect. Indirect (reflect. ValueOf (&x15)). Fieldbyname ("Z") FMT. Printf ("x15:%v \tcan be addressable and set:%t,%t\n", x15, V.canaddr (), V.canset ())//true,falsev = reflect. Indirect (reflect. ValueOf (&s{})) Fmt. Printf ("x15.1:%v \tcan be addressable and set:%t,%t\n", &s{}, V.canaddr (), V.canset ())//true,truevarx16 = Mv = reflect. ValueOf (x16) fmt. Printf ("x16:%p \tcan be addressable and set:%t,%t\n", x16, V.canaddr (), V.canset ())//false,falsevarX17 = Mv = reflect. Indirect (reflect. ValueOf (&x17)) fmt. Printf ("x17:%p \tcan be addressable and set:%t,%t\n", X17, V.canaddr (), V.canset ())//true,truevarx18Interface{} = &X11V = reflect. ValueOf (x18) fmt. Printf ("x18:%v \tcan be addressable and set:%t,%t\n", x18, V.canaddr (), V.canset ())//false,falsevarx19Interface{} = &X11V = reflect. ValueOf (x19). Elem () fmt. Printf ("x19:%v \tcan be addressable and set:%t,%t\n", x19, V.canaddr (), V.canset ())//true,truevarx20 = [...]int{1,2,3}v = reflect. ValueOf ([...]int{1,2,3}) fmt. Printf ("x20:%v \tcan be addressable and set:%t,%t\n", x20, V.canaddr (), V.canset ())//false,false}

Resources

    • http://www.tapirgames.com/blog/golang-unofficial-faq#unaddressable-values
    • https:// Blog.golang.org/laws-of-reflection
    • https://stackoverflow.com/questions/25384640/ Why-golang-reflect-makeslice-returns-un-addressable-value
    • http://grokbase.com/t/gg/golang-nuts/ 13bwpzedxh/go-nuts-golang-reflect-addressable-is-not-consistency
    • https://github.com/golang/go/issues/ 11865
    • Https://stackoverflow.com/questions/20224478/dereferencing-a-map-index-in-golang
    • https:/ /stackoverflow.com/questions/38168329/why-are-map-values-not-addressable
    • https://stackoverflow.com/ Questions/40793289/go-struct-literals-why-is-this-one-addressable
    • https://groups.google.com/forum/#! TOPIC/GOLANG-NUTS/FNTCX9R_PBM
    • https://stackoverflow.com/questions/24318389/ Golang-elem-vs-indirect-in-the-reflect-package
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.