go - 如何使用派生类型进行 sync.Map

标签 go

我的目标是拥有一个我可以派生并添加额外方法的自定义类型,例如,在使用 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

Struct types

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

Selectors

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.LoadOrStorex.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/

相关文章:

go - 交换两个数字 golang

Go找不到指定的文件

go - 如何从 STDIN 读取 “postpone”

Google Golang SDK 使用自定义 CA 包

jquery - 如何在使用 jquery 表单提交时从 golang 重定向到另一个模板?

Go:接口(interface)方法调用

go - 工作代码上未定义 : syscall. SIGURG

json - 可以使用 panic/recover 作为测试成功类型断言的方法吗?

go - 在 OSX 上交叉编译 Go?

go - 堆栈跟踪和 golang 错误。Unwrap()