带通道的 Golang 内存参考
Golang memory reference with Channels
当我尝试运行这段代码时,结果是。
{Yellow 99}
{Yellow 10}
重发link
package main
import (
"fmt"
"sync"
)
type Fruit struct {
color string
price int
}
func (f *Fruit) UpdatePrice(newPrice int) {
f.price = newPrice
}
func main() {
mango := Fruit{color: "Yellow", price: 10}
var wg sync.WaitGroup
one := make(chan Fruit)
wg.Add(1)
go func() {
defer wg.Done()
freshMango := <- one
freshMango.UpdatePrice(99)
fmt.Println(freshMango)
}()
one <- mango
wg.Wait()
fmt.Println(mango)
}
由于我更新了水果的价格,我希望这也能反映在芒果的最终印刷品中,但两者的价值不同。谁能详细说明这种情况下发生了什么?
您目前正在将 Fruit 对象的副本传递到您的 "one" 频道。您需要将指向该对象的指针传递给您的频道,并允许频道支持 *Fruit 而不是 Fruit。
package main
import (
"fmt"
"sync"
)
type Fruit struct {
color string
price int
}
func (f *Fruit) UpdatePrice(newPrice int) {
f.price = newPrice
}
func main() {
mango := Fruit{color: "Yellow", price: 10}
var wg sync.WaitGroup
one := make(chan *Fruit)
wg.Add(1)
go func() {
defer wg.Done()
var freshMango *Fruit
freshMango = <- one
freshMango.UpdatePrice(99)
fmt.Println(*freshMango)
}()
one <- &mango
wg.Wait()
fmt.Println(mango)
}
package main
import (
"fmt"
"sync"
)
type Fruit struct {
color string
price int
}
func (f *Fruit) UpdatePrice(newPrice int) {
f.price = newPrice
}
func main() {
// instead of pushing a copy of a Fruit struct you need to push a pointer of Fruit into the channel
mango := &Fruit{color: "Yellow", price: 10}
var wg sync.WaitGroup
one := make(chan *Fruit)
wg.Add(1)
go func() {
defer wg.Done()
freshMango := <- one
freshMango.UpdatePrice(99)
fmt.Println(freshMango)
}()
one <- mango
wg.Wait()
fmt.Println(mango)
}
Golang 在将每个 none 指针值传递给函数、通道等之前复制它
将指针从一个 goroutine 传递到另一个 goroutine 不是好的做法。它会产生非常讨厌的错误,因为两个 goroutines 都可以操纵底层类型。
任何有权访问此指针的 goroutine 都可以操作底层类型,并且没有强制执行应如何操作此类型的命令。
在本地机器上编译这个程序
package main
import (
"fmt"
"sync"
)
func main() {
i := new(int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
*i += 10
wg.Done()
}()
wg.Add(1)
go func() {
*i *= 10
wg.Done()
}()
wg.Add(1)
go func() {
*i = *i / 10
wg.Done()
}()
wg.Add(1)
go func() {
*i += 10
wg.Done()
}()
wg.Add(1)
go func() {
*i += 10
wg.Done()
}()
wg.Wait()
fmt.Println(*i)
}
现在运行这个go程序连续1000次
for i in {1..1000}; do ./main; done
如果你运行这个程序那么你会看到结果将是"randomly"。
当我尝试运行这段代码时,结果是。
{Yellow 99}
{Yellow 10}
重发link
package main
import (
"fmt"
"sync"
)
type Fruit struct {
color string
price int
}
func (f *Fruit) UpdatePrice(newPrice int) {
f.price = newPrice
}
func main() {
mango := Fruit{color: "Yellow", price: 10}
var wg sync.WaitGroup
one := make(chan Fruit)
wg.Add(1)
go func() {
defer wg.Done()
freshMango := <- one
freshMango.UpdatePrice(99)
fmt.Println(freshMango)
}()
one <- mango
wg.Wait()
fmt.Println(mango)
}
由于我更新了水果的价格,我希望这也能反映在芒果的最终印刷品中,但两者的价值不同。谁能详细说明这种情况下发生了什么?
您目前正在将 Fruit 对象的副本传递到您的 "one" 频道。您需要将指向该对象的指针传递给您的频道,并允许频道支持 *Fruit 而不是 Fruit。
package main
import (
"fmt"
"sync"
)
type Fruit struct {
color string
price int
}
func (f *Fruit) UpdatePrice(newPrice int) {
f.price = newPrice
}
func main() {
mango := Fruit{color: "Yellow", price: 10}
var wg sync.WaitGroup
one := make(chan *Fruit)
wg.Add(1)
go func() {
defer wg.Done()
var freshMango *Fruit
freshMango = <- one
freshMango.UpdatePrice(99)
fmt.Println(*freshMango)
}()
one <- &mango
wg.Wait()
fmt.Println(mango)
}
package main
import (
"fmt"
"sync"
)
type Fruit struct {
color string
price int
}
func (f *Fruit) UpdatePrice(newPrice int) {
f.price = newPrice
}
func main() {
// instead of pushing a copy of a Fruit struct you need to push a pointer of Fruit into the channel
mango := &Fruit{color: "Yellow", price: 10}
var wg sync.WaitGroup
one := make(chan *Fruit)
wg.Add(1)
go func() {
defer wg.Done()
freshMango := <- one
freshMango.UpdatePrice(99)
fmt.Println(freshMango)
}()
one <- mango
wg.Wait()
fmt.Println(mango)
}
Golang 在将每个 none 指针值传递给函数、通道等之前复制它
将指针从一个 goroutine 传递到另一个 goroutine 不是好的做法。它会产生非常讨厌的错误,因为两个 goroutines 都可以操纵底层类型。
任何有权访问此指针的 goroutine 都可以操作底层类型,并且没有强制执行应如何操作此类型的命令。
在本地机器上编译这个程序
package main
import (
"fmt"
"sync"
)
func main() {
i := new(int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
*i += 10
wg.Done()
}()
wg.Add(1)
go func() {
*i *= 10
wg.Done()
}()
wg.Add(1)
go func() {
*i = *i / 10
wg.Done()
}()
wg.Add(1)
go func() {
*i += 10
wg.Done()
}()
wg.Add(1)
go func() {
*i += 10
wg.Done()
}()
wg.Wait()
fmt.Println(*i)
}
现在运行这个go程序连续1000次
for i in {1..1000}; do ./main; done
如果你运行这个程序那么你会看到结果将是"randomly"。