goテクニック共有(二)

2799 ワード

これは一連の文章で、主にgoの使用提案とテクニックを共有して、毎回3点を共有して、あなたが収穫があることを望んでいます.

1 mapへの同時アクセス

package main

import "sync"

type Map struct {
    sync.RWMutex
    Data map[int]int
}

func main() {
    m := Map{}
    m.Data = make(map[int]int)

    for i := 0; i < 100000; i++ {
        go m.Write(i, i)
        go m.Read(i)
    }
}

func (m *Map) Read(key int) int {
    m.RLock()
    value := m.Data[key]
    m.RUnlock()
    return value
}

func (m *Map) Write(key int, value int) {
    m.Lock()
    m.Data[key] = value
    m.Unlock()
}

注記ロック解除とロック解除のコード:
func (m *Map) Read(key int) int {
    // m.RLock()
    value := m.Data[key]
    // m.RUnlock()
    return value
}

func (m *Map) Write(key int, value int) {
    // m.Lock()
    m.Data[key] = value
    // m.Unlock()
}

/*
fatal error: concurrent map read and map write
 
fatal error: concurrent map writes
*/

マルチパス同時アクセスmapでは、fatal error:concurrent map read and map writeまたはfatal error:concurrent map writesというエラーメッセージが表示される可能性があるため、マルチパスでmapに同時アクセスするには、syncを読み書きロックする同期メカニズムが必要である.RWMutexはmapに対する同時アクセス制御を実現し、mapとsyncを実現する.RWMutexをカプセル化すると、mapへの安全な同時アクセスが可能になります.例では、ロックとロック解除のコードを注釈すると、実行時にmapへの同時アクセスエラーが発生します.

2構造体がjson文字列に変換されたときにフィールドを無視

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    Name string
    Age  int
    Addr string `json:"-"`
    // addr string
}

func main() {
    jsonStr, _ := json.Marshal(User{"user1", 12, "addr"})
    fmt.Printf("%s
", jsonStr) } /* {"Name":"user1","Age":12} */

構造体をjson文字列に変換する場合、一部のフィールドを無視するには、そのフィールドの後ろに`json:"-"`を追加することで実現でき、tagを追加した後、json文字列に変換するとフィールドは無視されます.もちろん、このフィールドの頭文字を小文字に変更することで実現することもできますが、そうするとこのフィールドは他のパッケージにも隠されており、2つの方法にはそれぞれメリットとデメリットがあり、比較して使用することができます.

3 2つの構造体が等しいか否かを判断する

package main

import (
    "fmt"
    "reflect"
)

type User struct {
    Name string
    Age  int
    Addr string
}

func NewUser(name string, age int) User {
    u := User{}
    u.Name = name
    u.Age = age
    return u
}

func main() {
    u1 := NewUser("user1", 12)
    u2 := NewUser("user1", 12)
    fmt.Println(reflect.DeepEqual(u1, u2))
    fmt.Println(reflect.DeepEqual([]int{1, 2}, []int{1, 2}))
    fmt.Println(reflect.DeepEqual([2]int{1, 2}, [2]int{1, 2}))
    fmt.Println(reflect.DeepEqual(map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 2: 2}))
}

/*
true
true
true
true
*/

go言語の使用中に、2つの構造体が「等しい」かどうか、すなわち構造体フィールドとフィールド値が同じかどうかを比較する必要がある場合があります.自分で比較関数を実装する場合、構造体フィールドが多い場合は面倒です.reflectを使用する.DeepEqualは2つの構造体が等しいかどうかを判断することができるが,一定の性能影響を及ぼす.また、reflect.DeepEqualは構造体だけでなく,スライス,配列,辞書なども比較できる.