One Question When Using Slice

Code:

package main

import (
    "fmt"
    "sync"
)

type Data struct {
    A []int32
    B []string
}

func main() {
    channel := make(chan Data)
    data := Data{A: make([]int32, 0, 1), B: make([]string, 0, 1)}

    fmt.Printf("Before gorountine addr, A: %p\n", data.A)
    fmt.Printf("Before gorountine addr, B: %p\n", data.B)
    wg := new(sync.WaitGroup)
    wg.Add(1)
    go func() {
        for d := range channel {
            fmt.Printf("goroutine addr before append, A: %p\n", d.A)
            fmt.Printf("goroutine addr before append, B: %p\n", d.B)
            d.A = append(d.A, 23)
            d.B = append(d.B, "23")
            //d.A[0] = 23
            //d.B[0] = "23"
            fmt.Printf("goroutine addr after append, A: %p\n", d.A)
            fmt.Printf("goroutine addr after append, B: %p\n", d.B)
            fmt.Println(d)
        }
        wg.Done()
    }()

    fmt.Printf("Before: %v\n", data)
    channel <- data
    close(channel)
    wg.Wait()
    fmt.Printf("After gorountine addr, A: %p\n", data.A)
    fmt.Printf("After gorountine addr, B: %p\n", data.B)
    fmt.Printf("After: %v\n", data)
}

We can see that the slice within the struct in master && goroutine process has the same addr.
but the result is

Before gorountine addr, A: 0xc82000a2bc
Before gorountine addr, B: 0xc82000a2e0
Before: {[] []}
goroutine addr before append, A: 0xc82000a2bc
goroutine addr before append, B: 0xc82000a2e0
goroutine addr after append, A: 0xc82000a2bc
goroutine addr after append, B: 0xc82000a2e0
{[23] [23]}
After gorountine addr, A: 0xc82000a2bc
After gorountine addr, B: 0xc82000a2e0
After: {[] []}

why the data is empty?

if i remove append method, like this:

package main

import (
    "fmt"
    "sync"
)

type Data struct {
    A []int32
    B []string
}

func main() {
    channel := make(chan Data)
    data := Data{A: make([]int32, 1, 1), B: make([]string, 1, 1)}

    fmt.Printf("Before gorountine addr, A: %p\n", data.A)
    fmt.Printf("Before gorountine addr, B: %p\n", data.B)
    wg := new(sync.WaitGroup)
    wg.Add(1)
    go func() {
        for d := range channel {
            fmt.Printf("goroutine addr before append, A: %p\n", d.A)
            fmt.Printf("goroutine addr before append, B: %p\n", d.B)
            //d.A = append(d.A, 23)
            //d.B = append(d.B, "23")
            d.A[0] = 23
            d.B[0] = "23"
            fmt.Printf("goroutine addr after append, A: %p\n", d.A)
            fmt.Printf("goroutine addr after append, B: %p\n", d.B)
            fmt.Println(d)
        }
        wg.Done()
    }()

    fmt.Printf("Before: %v\n", data)
    channel <- data
    close(channel)
    wg.Wait()
    fmt.Printf("After gorountine addr, A: %p\n", data.A)
    fmt.Printf("After gorountine addr, B: %p\n", data.B)
    fmt.Printf("After: %v\n", data)
}

i can get this:

Before gorountine addr, A: 0xc82000a2bc
Before gorountine addr, B: 0xc82000a2e0
Before: {[0] []}
goroutine addr before append, A: 0xc82000a2bc
goroutine addr before append, B: 0xc82000a2e0
goroutine addr after append, A: 0xc82000a2bc
goroutine addr after append, B: 0xc82000a2e0
{[23] [23]}
After gorountine addr, A: 0xc82000a2bc
After gorountine addr, B: 0xc82000a2e0
After: {[23] [23]}

as all we know, slice is a reference. Even though the struct is copied, the copied slice refer to the same placeā€¦
so i think it can be changed in other goroutine

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.