猿问

为什么这个golang指针地址在goroutine中替换时不会改变?

我的理解是,当我创建一个对象时,foo := &bar{}我正在为该对象分配新内存。那么,当我尝试在 goroutine 中替换 *foo 时,为什么它没有获得新的指针地址?


package main


import (

    "fmt"

    "math/rand"

    "sync"

    "time"

)


type pointerToObjects struct {

    objs *objects

}

type objects struct {

    sliceOfObject []*object

}

type object struct {

    number  int

    boolean bool

}


func main() {

    p := &pointerToObjects{objs: newObjects()}

    mu := &sync.Mutex{}


    for _, o := range p.objs.sliceOfObject {

        o.setBool(true)

    }

    // goroutine 1

    go func() {

        ticker := time.NewTicker(time.Second)

        defer ticker.Stop()

        for range ticker.C {

            mu.Lock()

            fmt.Printf("objects pointer: %v\n", &p.objs)

            for i, o := range p.objs.sliceOfObject {

                fmt.Printf("i: %d p: %v n: %d b: %t\n", i, &o, o.number, o.boolean)

            }

            fmt.Print("---\n")

            mu.Unlock()

        }

    }()

    // goroutine 2

    go func() {

        ticker := time.NewTicker(time.Second * 2)

        defer ticker.Stop()

        for range ticker.C {

            newObjects := &objects{sliceOfObject: newSliceOfObject()}

            mu.Lock()

            p.objs = newObjects

            mu.Unlock()

            fmt.Printf("replaced: %v <-- %v \n", &p.objs, &newObjects)

        }

    }()


    // let the goroutines run for 10 seconds

    time.Sleep(time.Second * 10)

}

func newObjects() *objects {

    objs := &objects{}

    objs.sliceOfObject = newSliceOfObject()

    return objs

}


func newSliceOfObject() []*object {

    var sliceObjs []*object

    for i := 0; i < 3; i++ {

        sliceObjs = append(sliceObjs, newObject())

    }

    return sliceObjs

}

func newObject() *object {

    return &object{number: rand.Int()}

}


func (obj *object) setBool(b bool) {

    obj.boolean = b

}

运行时,值会按我的预期更新,但指向的指针p保持objects不变。我希望它会在我打电话时更新*p.objs = *newObjects

这是编译器的把戏吗?如何获取“对象指针”以更新到新位置?我需要使用更明确的指针吗?

编辑:修复了比赛条件并尝试分配p.objs = newObjects但没有成功。


慕无忌1623718
浏览 117回答 1
1回答

哆啦的时光机

除打印输出外,该程序按您预期的方式工作。要打印变量的值,请使用 fmt.Printf 参数列表中的变量。不要传递变量的地址。变量的值和变量的地址是不同的东西。为了更好地查看指针,请使用%p动词而不是. 打印指针%v。这是一个例子。改变&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Printf("replaced:&nbsp;%v&nbsp;<--&nbsp;%v&nbsp;\n",&nbsp;&p.objs,&nbsp;&newObjects)至&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Printf("replaced:&nbsp;%p&nbsp;<--&nbsp;%p&nbsp;\n",&nbsp;p.objs,&nbsp;newObjects)标题中提到的与使用 goroutine 无关的问题。
随时随地看视频慕课网APP

相关分类

Go
我要回答