我的目标是拥有一个我可以派生并添加额外方法的自定义类型,例如,在使用 map 时这有效:
package main
import "fmt"
type myMap map[string]string
func (m *myMap) Add() {
_, ok := (*m)["test"]
println(ok)
}
func main() {
x := &myMap{}
fmt.Printf("x = %+v\n", x)
}
但如果想要与sync.Map相同怎么做?我目前正在尝试这个:https://play.golang.org/p/8PjpPY-Sjq
package main
import (
"fmt"
"sync"
)
type myMap sync.Map
func (m *myMap) Add() {
_, ok := (*m).Load("test")
println(ok)
}
func main() {
x := &myMap{}
fmt.Printf("x = %+v\n", x)
}
但是得到这个错误:
(*m).Load undefined (type myMap has no field or method Load)
有什么想法吗?
最佳答案
The Go Programming Language Specification
A struct is a sequence of named elements, called fields, each of which has a name and a type. Field names may be specified explicitly (IdentifierList) or implicitly (EmbeddedField). Within a struct, non-blank field names must be unique.
StructType = "struct" "{" { FieldDecl ";" } "}" . FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] . EmbeddedField = [ "*" ] TypeName . Tag = string_lit .
A field declared with a type but no explicit field name is called an embedded field. An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.
A field or method f of an embedded field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.
Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.
Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:
If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
使用struct
的嵌入字段。例如,
package main
import (
"fmt"
"sync"
)
type myMap struct {
sync.Map
}
func (m *myMap) Add(key, value interface{}) bool {
_, loaded := m.LoadOrStore(key, value)
return !loaded
}
func main() {
x := &myMap{}
k := "test"
ok := x.Add(k, 42)
fmt.Println(ok)
v, ok := x.Load(k)
fmt.Println(k, v, ok)
}
Playground :https://play.golang.org/p/YCNeiYVhlT
输出:
true
test 42 true
The Go Programming Language Specification
For a primary expression x that is not a package name, the selector expression
x.f
denotes the field or method f of the value x (or sometimes *x; see below). The identifier f is called the (field or method) selector; it must not be the blank identifier. The type of the selector expression is the type of f. If x is a package name, see the section on qualified identifiers.
A selector f may denote a field or method f of a type T, or it may refer to a field or method f of a nested embedded field of T. The number of embedded fields traversed to reach f is called its depth in T. The depth of a field or method f declared in T is zero. The depth of a field or method f declared in an embedded field A in T is the depth of f in A plus one.
Rule 1:
For a value x of type T or *T where T is not a pointer or interface type, x.f denotes the field or method at the shallowest depth in T where there is such an f. If there is not exactly one f with shallowest depth, the selector expression is illegal.
有时,在嵌套嵌入的复杂情况下会出现歧义。如果是这样,请明确指定完整限定符。例如,m.Map.LoadOrStore
和 x.Map.Load
。
package main
import (
"fmt"
"sync"
)
type myMap struct {
sync.Map
}
func (m *myMap) Add(key, value interface{}) bool {
_, loaded := m.Map.LoadOrStore(key, value)
return !loaded
}
func main() {
x := &myMap{}
k := "test"
ok := x.Add(k, 42)
fmt.Println(ok)
v, ok := x.Map.Load(k)
fmt.Println(k, v, ok)
}
关于go - 如何使用派生类型进行 sync.Map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47178816/