0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[golang] for ループの一時変数はそれぞれ別のメモリ領域(アドレス)に配置される

Last updated at Posted at 2024-12-15

目的

for ループの一時変数はそれぞれ別のメモリ領域(アドレス)に配置されることを知る。

これは、v1.22 で導入された仕様です。

一応インストール手順

$ sudo rm -rf /usr/local/go
$ wget https://go.dev/dl/go1.21.0.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
$ rm -rf go1.21.0.linux-amd64.tar.gz
$ echo "export PATH=\$PATH:/usr/local/go/bin/:\$HOME/go/bin" >> $HOME/.bashrc
$ source $HOME/.bashrc
~/praprago$ go mod init github.com/XXX/praprago
go.mod
module github.com/XXX/praprago

go 1.21.0

$ go version && go env GOROOT && go env GOPATH
go version go1.21.0 linux/amd64
/usr/local/go
/home/ubuntu/go

検証

(1)

main.go
package main

import "fmt"

// go run .
func main() {
	fmt.Println(" ================================================================= (1)")
	PraFor1()
}

pra_for.go
package main

import (
	"fmt"
)

type MyStruct struct {
	Name string
	Age  int
}

// ////////////////////////////////////////////////////
// //////////////////////////////////////////////////// (1)
func PraFor1() {
	store := make(map[int]*MyStruct)
	// var store map[int]*MyStruct // これだと store[i] = &v の部分でエラーになる。

	myStructs := []MyStruct{
		{"AAA", 1},
		{"BBB", 2},
		{"CCC", 3},
	}
	for i, v := range myStructs {
		fmt.Println("BBBBBBBBBB_222333")
		fmt.Println("i:", i)
		fmt.Println("v:", v)
		fmt.Printf("&v: %p\n", &v)
		store[i] = &v
	}
	fmt.Println("AAAAAAAAAA_111222")
	fmt.Println("store:", store)
	fmt.Printf("store[0]: %p\n", store[0])
	fmt.Printf("*store[1]: %v\n", *store[0])
	fmt.Printf("store[1]: %p\n", store[1])
	fmt.Printf("*store[1]: %v\n", *store[1])
	fmt.Printf("store[2]: %p\n", store[2])
	fmt.Printf("*store[2]: %v\n", *store[2])
}

v1.22 以前(検証環境は V1.21.0)

~/praprago$ go run .
 ================================================================= (1)
BBBBBBBBBB_222333
i: 0
v: {AAA 1}
&v: 0xc000010018
BBBBBBBBBB_222333
i: 1
v: {BBB 2}
&v: 0xc000010018
BBBBBBBBBB_222333
i: 2
v: {CCC 3}
&v: 0xc000010018
AAAAAAAAAA_111222
store: map[0:0xc000010018 1:0xc000010018 2:0xc000010018]
store[0]: 0xc000010018
*store[1]: {CCC 3}
store[1]: 0xc000010018
*store[1]: {CCC 3}
store[2]: 0xc000010018
*store[2]: {CCC 3}

v1.22 以降(検証環境は V1.23.2 )

~/praprago$ go run .
 ================================================================= (1)
BBBBBBBBBB_222333
i: 0
v: {AAA 1}
&v: 0xc000010018
BBBBBBBBBB_222333
i: 1
v: {BBB 2}
&v: 0xc000010048
BBBBBBBBBB_222333
i: 2
v: {CCC 3}
&v: 0xc000010078
AAAAAAAAAA_111222
store: map[0:0xc000010018 1:0xc000010048 2:0xc000010078]
store[0]: 0xc000010018
*store[1]: {AAA 1}
store[1]: 0xc000010048
*store[1]: {BBB 2}
store[2]: 0xc000010078
*store[2]: {CCC 3}

(2)

~/praprago$ tree -La 3 -I .git
.
├── go.mod
└── main.go

1 directory, 2 files
main.go
package main

import "fmt"

func main() {
	numGoroutines := 5

	done := make(chan bool, numGoroutines)

	for i := 0; i < numGoroutines; i++ {
		go func() {
			fmt.Printf("goroutine %d is running\n", i)
			done <- true
		}()
	}
	for i := 0; i < numGoroutines; i++ {
		<-done
	}

	fmt.Println("All goroutines finished")
}

v1.22 以前(検証環境は V1.21.0)

それぞれのループの i はアドレスが同じなので、仮に、i = 1 で呼ばれている groutine でも、実際にiを参照するタイミングで、次のループに進んでiが増えていたら、その瞬間の iを使うことになる。

下記を見ると、いずれのgroroutine の開始前に全てのループが終了し、全ての goroutine はループ終了後の i を使うことになる。

~/praprago$ go run main.go
goroutine 5 is running
goroutine 5 is running
goroutine 5 is running
goroutine 5 is running
goroutine 5 is running
All goroutines finished

v1.22 以降(検証環境は V1.23.2 )

~/praprago$ go run main.go
goroutine 4 is running
goroutine 0 is running
goroutine 1 is running
goroutine 2 is running
goroutine 3 is running
All goroutines finished

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?