20230223日志

20230223日志

2023年2月23日
2023
202302, go, range

go #

value copy #

type account struct {
    balance float32
}

accounts := []account{
    {balance: 100.},
    {balance: 200.},
    {balance: 300.},
}
for _, a := range accounts {
    a.balance += 1000
}

并不会改变accounts的值, 因为在遍历时struct会被copy

  1. 方案1:
for i := range accounts {
    accounts[i].balance += 1000
}

  1. 方案2:
for i := range accounts {
    accounts[i].balance += 1000
}
  1. 方案3(关注性能时需要考虑指针的不可预测性):
accounts := []*account{
    {balance: 100.},
    {balance: 200.},
    {balance: 300.},
}
for _, a := range accounts {
    a.balance += 1000
}

Ignoring how arguments are evaluated in range loops #

s := []int{0, 1, 2}
for range s {
    s = append(s, 10)
}

range_is_copy

s := []int{0, 1, 2}
for i := 0; i < len(s); i++ {
    s = append(s, 10)
}

for 循环不会停下来

ch1 := make(chan int, 3)
go func() {
    ch1 <- 0
    ch1 <- 1
    ch1 <- 2
    close(ch1)
}()
ch2 := make(chan int, 3)
go func() {
    ch2 <- 10
    ch2 <- 11
    ch2 <- 12
    close(ch2)
}()
ch := ch1
for v := range ch {
    fmt.Println(v)
    ch = ch2
}

range ch 也会创建新的变量指向ch, 因此 ch=ch2并不能改变range的对象

a := [3]int{0, 1, 2}
for i, v := range a {
    a[2] = 10
    if i == 2 {
        fmt.Println(v)
}
}

!range_array_is_copy

range数组(not slice)会完整的copy一份数据

Ignoring the impact of using pointer elements in range loops #

type Info struct {
    name string
}
s := map[string]Info{
    "1": {name: "zzlion"},
    "2": {name: "lixiong"},
}
a := s["1"]
a.name = "null"
fmt.Printf("%v\n", s)

map取出的值也是copy, 修改后想在原map中体现,需要重新赋值回去

type Customer struct {
    ID string
    Balance float64
}
type Store struct {
    m map[string]*Customer
}
func (s *Store) storeCustomers(customers []Customer) {
    for _, customer := range customers {
        s.m[customer.ID] = &customer
}
}

!range_var_is_one

range中的变量始终是同一个对象

解决方案1:

func (s *Store) storeCustomers(customers []Customer) {
    for _, customer := range customers {
        current := customer
        s.m[current.ID] = &current
    }
}

解决方案2:

func (s *Store) storeCustomers(customers []Customer) {
    for i := range customers {
        customer := &customers[i]
        s.m[customer.ID] = customer
    }
}

Making wrong assumptions during map iterations #

  1. map的key是无序的, 遍历不能保证插入的顺序
  2. 遍历时对map插入数据,行为是未知的