Source File
value.go
Belonging Package
reflect
}
type flag uintptr
const (
flagKindWidth = 5 // there are 27 kinds
flagKindMask flag = 1<<flagKindWidth - 1
flagStickyRO flag = 1 << 5
flagEmbedRO flag = 1 << 6
flagIndir flag = 1 << 7
flagAddr flag = 1 << 8
flagMethod flag = 1 << 9
flagMethodShift = 10
flagRO flag = flagStickyRO | flagEmbedRO
)
func ( flag) () Kind {
return Kind( & flagKindMask)
}
func ( flag) () flag {
if &flagRO != 0 {
return flagStickyRO
}
return 0
}
switch {
case ifaceIndir():
if .flag&flagIndir == 0 {
panic("bad indir")
:= .ptr
:= unsafe_New()
typedmemmove(, , )
=
}
.word =
.typ =
return
}
func ( interface{}) Value {
if Kind(&flagKindMask) != {
panic(&ValueError{methodName(), .kind()})
}
}
func ( flag) () {
if == 0 || &flagRO != 0 {
.mustBeExportedSlow()
}
}
func ( flag) () {
if == 0 {
panic(&ValueError{methodNameSkip(), Invalid})
}
if &flagRO != 0 {
panic("reflect: " + methodNameSkip() + " using value obtained using unexported field")
}
}
func ( flag) () {
if &flagRO != 0 || &flagAddr == 0 {
.mustBeAssignableSlow()
}
}
func ( flag) () {
if == 0 {
panic(&ValueError{methodNameSkip(), Invalid})
if &flagRO != 0 {
panic("reflect: " + methodNameSkip() + " using value obtained using unexported field")
}
if &flagAddr == 0 {
panic("reflect: " + methodNameSkip() + " using unaddressable value")
}
}
:= (*funcType)(unsafe.Pointer(.typ))
var (
unsafe.Pointer
Value
*rtype
)
if .flag&flagMethod != 0 {
=
, , = methodReceiver(, , int(.flag)>>flagMethodShift)
} else if .flag&flagIndir != 0 {
= *(*unsafe.Pointer)(.ptr)
} else {
= .ptr
}
if == nil {
panic("reflect.Value.Call: call of nil function")
}
:= == "CallSlice"
:= .NumIn()
if {
if !.IsVariadic() {
panic("reflect: CallSlice of non-variadic function")
}
if len() < {
panic("reflect: CallSlice with too few input arguments")
}
if len() > {
panic("reflect: CallSlice with too many input arguments")
}
} else {
if .IsVariadic() {
--
}
if len() < {
panic("reflect: Call with too few input arguments")
}
if !.IsVariadic() && len() > {
panic("reflect: Call with too many input arguments")
}
}
for , := range {
if .Kind() == Invalid {
panic("reflect: " + + " using zero Value argument")
}
}
for := 0; < ; ++ {
if , := [].Type(), .In(); !.AssignableTo() {
panic("reflect: " + + " using " + .String() + " as type " + .String())
}
}
:= len() -
:= MakeSlice(.In(), , )
:= .In().Elem()
for := 0; < ; ++ {
:= [+]
if := .Type(); !.AssignableTo() {
panic("reflect: cannot use " + .String() + " as type " + .String() + " in " + )
}
.Index().Set()
}
:=
= make([]Value, +1)
copy([:], )
[] =
}
:= len()
if != .NumIn() {
panic("reflect.Value.Call: wrong argument count")
}
:= .NumOut()
, , , , := funcLayout(, )
= unsafe_New()
}
:= uintptr(0)
typedmemclrpartial(, , 0, )
if > 0 {
+= - & (ptrSize - 1)
for , := range .out() {
:= []
if .typ == nil {
panic("reflect: function created by MakeFunc using " + funcName() +
" returned zero Value")
}
if .flag&flagRO != 0 {
panic("reflect: function created by MakeFunc using " + funcName() +
" returned value obtained from unexported field")
}
+= - & uintptr(.align-1)
if .size == 0 {
continue
}
:= add(, , "typ.size > 0")
* = true
func ( string, Value, int) ( *rtype, *funcType, unsafe.Pointer) {
:=
if .typ.Kind() == Interface {
:= (*interfaceType)(unsafe.Pointer(.typ))
if uint() >= uint(len(.methods)) {
panic("reflect: internal error: invalid method index")
}
:= &.methods[]
if !.nameOff(.name).isExported() {
panic("reflect: " + + " of unexported method")
}
:= (*nonEmptyInterface)(.ptr)
if .itab == nil {
panic("reflect: " + + " of method on nil interface value")
}
= .itab.typ
= unsafe.Pointer(&.itab.fun[])
= (*funcType)(unsafe.Pointer(.typeOff(.typ)))
} else {
= .typ
:= .typ.exportedMethods()
if uint() >= uint(len()) {
panic("reflect: internal error: invalid method index")
}
:= []
if !.typ.nameOff(.name).isExported() {
panic("reflect: " + + " of unexported method")
}
:= .typ.textOff(.ifn)
= unsafe.Pointer(&)
= (*funcType)(unsafe.Pointer(.typ.typeOff(.mtyp)))
}
return
}
func ( *methodValue, unsafe.Pointer, *bool) {
:= .rcvr
, , := methodReceiver("call", , .method)
, , , , := funcLayout(, )
if - > 0 {
typedmemmovepartial(, add(, , "argSize > argOffset"), , , -)
}
if .size- > 0 {
* = true
typedmemclr(, )
.Put()
return (*unsafeheader.Slice)(.ptr).Cap
}
panic(&ValueError{"reflect.Value.Cap", .kind()})
}
func ( Value) () complex128 {
:= .kind()
switch {
case Complex64:
return complex128(*(*complex64)(.ptr))
case Complex128:
return *(*complex128)(.ptr)
}
panic(&ValueError{"reflect.Value.Complex", .kind()})
}
func ( Value) () Value {
:= .kind()
switch {
case Interface:
var interface{}
if .typ.NumMethod() == 0 {
= *(*interface{})(.ptr)
} else {
= (interface{})(*(*interface {
()
})(.ptr))
}
:= unpackEface()
if .flag != 0 {
.flag |= .flag.ro()
}
return
case Ptr:
:= .ptr
if .flag&flagIndir != 0 {
= *(*unsafe.Pointer)()
if !.name.isExported() {
if .embedded() {
|= flagEmbedRO
} else {
|= flagStickyRO
}
func ( Value) ( string) Value {
.mustBe(Struct)
if , := .typ.FieldByName(); {
return .FieldByIndex(.Index)
}
return Value{}
}
func ( Value) ( func(string) bool) Value {
if , := .typ.FieldByNameFunc(); {
return .FieldByIndex(.Index)
}
return Value{}
}
:= (*unsafeheader.Slice)(.ptr)
if uint() >= uint(.Len) {
panic("reflect: slice index out of range")
}
:= (*sliceType)(unsafe.Pointer(.typ))
:= .elem
:= arrayAt(.Data, , .size, "i < s.Len")
:= flagAddr | flagIndir | .flag.ro() | flag(.Kind())
return Value{, , }
case String:
:= (*unsafeheader.String)(.ptr)
if uint() >= uint(.Len) {
panic("reflect: string index out of range")
}
:= arrayAt(.Data, , 1, "i < s.Len")
:= .flag.ro() | flag(Uint8) | flagIndir
return Value{uint8Type, , }
}
panic(&ValueError{"reflect.Value.Index", .kind()})
}
func ( Value) () ( interface{}) {
return valueInterface(, true)
}
func ( Value, bool) interface{} {
if .flag == 0 {
panic(&ValueError{"reflect.Value.Interface", Invalid})
}
panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
}
if .flag&flagMethod != 0 {
= makeMethodValue("Interface", )
}
return packEface()
}
func ( Value) () bool {
switch .kind() {
case Bool:
return !.Bool()
case Int, Int8, Int16, Int32, Int64:
return .Int() == 0
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return .Uint() == 0
case Float32, Float64:
return math.Float64bits(.Float()) == 0
case Complex64, Complex128:
:= .Complex()
return math.Float64bits(real()) == 0 && math.Float64bits(imag()) == 0
case Array:
for := 0; < .Len(); ++ {
if !.Index().() {
return false
}
}
return true
case Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer:
return .IsNil()
case String:
return .Len() == 0
case Struct:
for := 0; < .NumField(); ++ {
if !.Field().() {
return false
}
}
return true
panic(&ValueError{"reflect.Value.IsZero", .Kind()})
}
}
return (*unsafeheader.Slice)(.ptr).Len
return (*unsafeheader.String)(.ptr).Len
}
panic(&ValueError{"reflect.Value.Len", .kind()})
}
break
}
[] = copyVal(, , )
mapiternext()
}
return [:]
}
func ( *MapIter) () bool {
if .it == nil {
.it = mapiterinit(.m.typ, .m.pointer())
} else {
if mapiterkey(.it) == nil {
panic("MapIter.Next called on exhausted iterator")
}
mapiternext(.it)
}
return mapiterkey(.it) != nil
}
:= unsafe_New()
typedmemmove(, , )
return Value{, , | flagIndir}
}
return Value{, *(*unsafe.Pointer)(), }
}
func ( Value) ( int) Value {
if .typ == nil {
panic(&ValueError{"reflect.Value.Method", Invalid})
}
if .flag&flagMethod != 0 || uint() >= uint(.typ.NumMethod()) {
panic("reflect: Method index out of range")
}
if .typ.Kind() == Interface && .IsNil() {
panic("reflect: Method on nil interface value")
}
:= .flag.ro() | (.flag & flagIndir)
|= flag(Func)
|= flag()<<flagMethodShift | flagMethod
return Value{.typ, .ptr, }
}
func ( Value) ( complex128) bool {
:= .kind()
switch {
case Complex64:
return overflowFloat32(real()) || overflowFloat32(imag())
case Complex128:
return false
}
panic(&ValueError{"reflect.Value.OverflowComplex", .kind()})
}
func ( Value) ( float64) bool {
:= .kind()
switch {
case Float32:
return overflowFloat32()
case Float64:
return false
}
panic(&ValueError{"reflect.Value.OverflowFloat", .kind()})
}
func ( float64) bool {
if < 0 {
= -
}
return math.MaxFloat32 < && <= math.MaxFloat64
}
:= methodValueCall
return **(**uintptr)(unsafe.Pointer(&))
}
func ( Value) ( bool) ( Value, bool) {
:= (*chanType)(unsafe.Pointer(.typ))
if ChanDir(.dir)&RecvDir == 0 {
panic("reflect: recv on send-only channel")
}
:= .elem
= Value{, nil, flag(.Kind())}
var unsafe.Pointer
if ifaceIndir() {
= unsafe_New()
.ptr =
.flag |= flagIndir
} else {
= unsafe.Pointer(&.ptr)
}
, := chanrecv(.pointer(), , )
if ! {
= Value{}
}
return
}
func ( Value) ( Value, bool) ( bool) {
:= (*chanType)(unsafe.Pointer(.typ))
if ChanDir(.dir)&SendDir == 0 {
panic("reflect: send on recv-only channel")
}
.mustBeExported()
= .assignTo("reflect.Value.Send", .elem, nil)
var unsafe.Pointer
if .flag&flagIndir != 0 {
= .ptr
} else {
= unsafe.Pointer(&.ptr)
}
return chansend(.pointer(), , )
}
func ( Value) ( Value) {
.mustBeAssignable()
.mustBeExported() // do not let unexported x leak
var unsafe.Pointer
if .kind() == Interface {
= .ptr
}
= .assignTo("reflect.Set", .typ, )
if .flag&flagIndir != 0 {
if .ptr == unsafe.Pointer(&zeroVal[0]) {
typedmemclr(.typ, .ptr)
} else {
typedmemmove(.typ, .ptr, .ptr)
}
} else {
*(*unsafe.Pointer)(.ptr) = .ptr
}
}
func ( Value) ( complex128) {
.mustBeAssignable()
switch := .kind(); {
default:
panic(&ValueError{"reflect.Value.SetComplex", .kind()})
case Complex64:
*(*complex64)(.ptr) = complex64()
case Complex128:
*(*complex128)(.ptr) =
}
}
func ( Value) ( int64) {
.mustBeAssignable()
switch := .kind(); {
default:
panic(&ValueError{"reflect.Value.SetInt", .kind()})
case Int:
*(*int)(.ptr) = int()
case Int8:
*(*int8)(.ptr) = int8()
case Int16:
*(*int16)(.ptr) = int16()
case Int32:
*(*int32)(.ptr) = int32()
case Int64:
*(*int64)(.ptr) =
}
}
func ( Value) (, Value) {
.mustBe(Map)
.mustBeExported()
.mustBeExported()
:= (*mapType)(unsafe.Pointer(.typ))
= .assignTo("reflect.Value.SetMapIndex", .key, nil)
var unsafe.Pointer
if .flag&flagIndir != 0 {
= .ptr
} else {
= unsafe.Pointer(&.ptr)
}
if .typ == nil {
mapdelete(.typ, .pointer(), )
return
}
.mustBeExported()
= .assignTo("reflect.Value.SetMapIndex", .elem, nil)
var unsafe.Pointer
if .flag&flagIndir != 0 {
= .ptr
} else {
= unsafe.Pointer(&.ptr)
}
mapassign(.typ, .pointer(), , )
}
func ( Value) ( uint64) {
.mustBeAssignable()
switch := .kind(); {
default:
panic(&ValueError{"reflect.Value.SetUint", .kind()})
case Uint:
*(*uint)(.ptr) = uint()
case Uint8:
*(*uint8)(.ptr) = uint8()
case Uint16:
*(*uint16)(.ptr) = uint16()
case Uint32:
*(*uint32)(.ptr) = uint32()
case Uint64:
*(*uint64)(.ptr) =
case Uintptr:
*(*uintptr)(.ptr) = uintptr()
}
}
func ( Value) ( unsafe.Pointer) {
.mustBeAssignable()
.mustBe(UnsafePointer)
*(*unsafe.Pointer)(.ptr) =
}
func ( Value) (, int) Value {
var (
int
*sliceType
unsafe.Pointer
)
switch := .kind(); {
default:
panic(&ValueError{"reflect.Value.Slice", .kind()})
case Array:
if .flag&flagAddr == 0 {
panic("reflect.Value.Slice: slice of unaddressable array")
}
:= (*arrayType)(unsafe.Pointer(.typ))
= int(.len)
= (*sliceType)(unsafe.Pointer(.slice))
= .ptr
case Slice:
= (*sliceType)(unsafe.Pointer(.typ))
:= (*unsafeheader.Slice)(.ptr)
= .Data
= .Cap
case String:
:= (*unsafeheader.String)(.ptr)
if < 0 || < || > .Len {
panic("reflect.Value.Slice: string slice index out of bounds")
}
var unsafeheader.String
if < .Len {
= unsafeheader.String{Data: arrayAt(.Data, , 1, "i < s.Len"), Len: - }
}
return Value{.typ, unsafe.Pointer(&), .flag}
}
if < 0 || < || > {
panic("reflect.Value.Slice: slice index out of bounds")
}
func ( Value) (, , int) Value {
var (
int
*sliceType
unsafe.Pointer
)
switch := .kind(); {
default:
panic(&ValueError{"reflect.Value.Slice3", .kind()})
case Array:
if .flag&flagAddr == 0 {
panic("reflect.Value.Slice3: slice of unaddressable array")
}
:= (*arrayType)(unsafe.Pointer(.typ))
= int(.len)
= (*sliceType)(unsafe.Pointer(.slice))
= .ptr
case Slice:
= (*sliceType)(unsafe.Pointer(.typ))
:= (*unsafeheader.Slice)(.ptr)
= .Data
= .Cap
}
if < 0 || < || < || > {
panic("reflect.Value.Slice3: slice index out of bounds")
}
return .typ
}
:= int(.flag) >> flagMethodShift
func ( Value) () uint64 {
:= .kind()
:= .ptr
switch {
case Uint:
return uint64(*(*uint)())
case Uint8:
return uint64(*(*uint8)())
case Uint16:
return uint64(*(*uint16)())
case Uint32:
return uint64(*(*uint32)())
case Uint64:
return *(*uint64)()
case Uintptr:
return uint64(*(*uintptr)())
}
panic(&ValueError{"reflect.Value.Uint", .kind()})
}
type StringHeader struct {
Data uintptr
Len int
}
func (, Value) int {
:= .kind()
if != Array && != Slice {
panic(&ValueError{"reflect.Copy", })
}
if == Array {
.mustBeAssignable()
}
.mustBeExported()
:= .kind()
var bool
if != Array && != Slice {
= == String && .typ.Elem().Kind() == Uint8
if ! {
panic(&ValueError{"reflect.Copy", })
}
}
.mustBeExported()
:= .typ.Elem()
if ! {
:= .typ.Elem()
typesMustMatch("reflect.Copy", , )
}
var , unsafeheader.Slice
if == Array {
.Data = .ptr
.Len = .Len()
.Cap = .Len
} else {
= *(*unsafeheader.Slice)(.ptr)
}
if == Array {
.Data = .ptr
.Len = .Len()
.Cap = .Len
} else if == Slice {
= *(*unsafeheader.Slice)(.ptr)
} else {
:= *(*unsafeheader.String)(.ptr)
.Data = .Data
.Len = .Len
.Cap = .Len
}
return typedslicecopy(.common(), , )
}
func ([]runtimeSelect) ( int, bool)
const (
_ SelectDir = iota
SelectSend // case Chan <- Send
SelectRecv // case <-Chan:
SelectDefault // default
)
var []runtimeSelect
= make([]runtimeSelect, len())
= make([]runtimeSelect, len(), 4)
}
:= false
for , := range {
:= &[]
.dir = .Dir
switch .Dir {
default:
panic("reflect.Select: invalid Dir")
case SelectDefault: // default
if {
panic("reflect.Select: multiple default cases")
}
= true
if .Chan.IsValid() {
panic("reflect.Select: default case has Chan value")
}
if .Send.IsValid() {
panic("reflect.Select: default case has Send value")
}
case SelectSend:
:= .Chan
if !.IsValid() {
break
}
.mustBe(Chan)
.mustBeExported()
:= (*chanType)(unsafe.Pointer(.typ))
if ChanDir(.dir)&SendDir == 0 {
panic("reflect.Select: SendDir case using recv-only channel")
}
.ch = .pointer()
.typ = &.rtype
:= .Send
if !.IsValid() {
panic("reflect.Select: SendDir case missing Send value")
}
.mustBeExported()
= .assignTo("reflect.Select", .elem, nil)
if .flag&flagIndir != 0 {
.val = .ptr
} else {
.val = unsafe.Pointer(&.ptr)
}
case SelectRecv:
if .Send.IsValid() {
panic("reflect.Select: RecvDir case has Send value")
}
:= .Chan
if !.IsValid() {
break
}
.mustBe(Chan)
.mustBeExported()
:= (*chanType)(unsafe.Pointer(.typ))
if ChanDir(.dir)&RecvDir == 0 {
panic("reflect.Select: RecvDir case using send-only channel")
}
.ch = .pointer()
.typ = &.rtype
.val = unsafe_New(.elem)
}
}
, = rselect()
if [].dir == SelectRecv {
:= (*chanType)(unsafe.Pointer([].typ))
:= .elem
:= [].val
:= flag(.Kind())
if ifaceIndir() {
= Value{, , | flagIndir}
} else {
= Value{, *(*unsafe.Pointer)(), }
}
}
return , ,
}
func ( Type, , int) Value {
if .Kind() != Slice {
panic("reflect.MakeSlice of non-slice type")
}
if < 0 {
panic("reflect.MakeSlice: negative len")
}
if < 0 {
panic("reflect.MakeSlice: negative cap")
}
if > {
panic("reflect.MakeSlice: len > cap")
}
:= unsafeheader.Slice{Data: unsafe_NewArray(.Elem().(*rtype), ), Len: , Cap: }
return Value{.(*rtype), unsafe.Pointer(&), flagIndir | flag(Slice)}
}
func ( Type) Value {
return MakeMapWithSize(, 0)
}
escapes()
return unpackEface()
}
const maxZero = 1024
func ( Value) ( string, *rtype, unsafe.Pointer) Value {
if .flag&flagMethod != 0 {
= makeMethodValue(, )
}
switch {
func (, *rtype) func(Value, Type) Value {
switch .Kind() {
case Int, Int8, Int16, Int32, Int64:
switch .Kind() {
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtInt
case Float32, Float64:
return cvtIntFloat
case String:
return cvtIntString
}
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
switch .Kind() {
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtUint
case Float32, Float64:
return cvtUintFloat
case String:
return cvtUintString
}
case Float32, Float64:
switch .Kind() {
case Int, Int8, Int16, Int32, Int64:
return cvtFloatInt
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
return cvtFloatUint
case Float32, Float64:
return cvtFloat
}
case Complex64, Complex128:
switch .Kind() {
case Complex64, Complex128:
return cvtComplex
}
case String:
if .Kind() == Slice && .Elem().PkgPath() == "" {
switch .Elem().Kind() {
case Uint8:
return cvtStringBytes
case Int32:
return cvtStringRunes
}
}
case Slice:
if .Kind() == String && .Elem().PkgPath() == "" {
switch .Elem().Kind() {
case Uint8:
return cvtBytesString
case Int32:
return cvtRunesString
}
}
case Chan:
if .Kind() == Chan && specialChannelAssignability(, ) {
return cvtDirect
}
}
if haveIdenticalUnderlyingType(, , false) {
return cvtDirect
}
func ( flag, complex128, Type) Value {
:= .common()
:= unsafe_New()
switch .size {
case 8:
*(*complex64)() = complex64()
case 16:
*(*complex128)() =
}
return Value{, , | flagIndir | flag(.Kind())}
}
func ( flag, string, Type) Value {
:= New().Elem()
.SetString()
.flag = .flag&^flagAddr |
return
}
func ( flag, []byte, Type) Value {
:= New().Elem()
.SetBytes()
.flag = .flag&^flagAddr |
return
}
func ( flag, []rune, Type) Value {
:= New().Elem()
.setRunes()
.flag = .flag&^flagAddr |
return
}
:= unsafe_New()
typedmemmove(, , )
=
&^= flagAddr
}
return Value{, , .flag.ro() | } // v.flag.ro()|f == f?
}
func ( *rtype, , unsafeheader.Slice) int
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |