Sorry, This post is Japanese Only.
I'm verifying the address transfer in function of Go Launguage on WindowsPort.
The address transfer of Go Launguage is same as C language .
So we use both Pointer type or Value type as we like, but Using pointer is less allocated memories than using value.
さて、サンプルソース
package main
import(
"fmt"
"bufio"
"os"
)
// 構造体を定義
type H struct {
背番号 int
カナ byte
名前 string
住んでる所 string
性格 string
}
func GetManmoth(inarray []H) (out H){
fmt.Printf("受け取り構造体配列先頭アドレス:%p\n",&inarray)
for i,_ := range inarray{
if inarray[i].名前 == "マンモスハナアルキ" {
out = inarray[i]
}
}
fmt.Printf("返送構造体先頭アドレス:%p\n",&out)
return out
}
func GetJet(inarray []H) (out *H){
fmt.Printf("受け取り構造体配列先頭アドレス:%p\n",&inarray)
for i,_ := range inarray{
if inarray[i].名前 == "ジェットハナアルキ" {
out = &inarray[i]
}
}
fmt.Printf("返送構造体先頭アドレス:%p\n",out)
return out
}
// main関数
func main(){
// 構造体をそれぞれ初期化
oHanaaruki := H{1,'o', "オオハナアルキ", "地上", "ちょっと凶暴"}
mHanaaruki := H{2,'m', "マンモスハナアルキ", "地上", "のんびり"}
dHanaaruki := H{3,'d', "ダンボハナアルキ", "空中", "ぱたぱた系"}
jHanaaruki := H{4,'j', "ジェットハナアルキ", "空中", "ビュンビュン系"}
bHanaaruki := H{5,'b', "バニラ・ランモドキ", "樹上", "お色気派"}
// 構造体を配列に格納
hs := []H{oHanaaruki,mHanaaruki,dHanaaruki, jHanaaruki, bHanaaruki}
// 配列のサイズを確認
fmt.Printf("構造体メモリ展開個数:%d\n",len(hs))
fmt.Printf("構造体配列先頭アドレス:%p\n",&hs)
mh := GetManmoth(hs)
fmt.Printf("返送構造体先頭アドレス:%p\n",&mh)
jh := GetJet(hs)
fmt.Printf("返送構造体ポインタアドレス:%p\n",jh)
ins := bufio.NewReader(os.Stdin)
for{
line, err := ins.ReadString('\n')
if err == os.EOF {
fmt.Printf(";;;End\n")
break
}
fmt.Printf(";;;%s",line)
}
}
構造体の展開とアドレスのサーチについては、前回と同じ方法なので、割愛。
今度は、構造体を実際に、関数でやりとりしてみたのね。
構造体メモリ展開個数:5
構造体配列先頭アドレス:0x576260
受け取り構造体配列先頭アドレス:0x5763e0
返送構造体先頭アドレス:0x574740
返送構造体先頭アドレス:0x574760
受け取り構造体配列先頭アドレス:0x5763a0
返送構造体先頭アドレス:0x589060
返送構造体ポインタアドレス:0x589060
この時、0x576260と0x5763e0と0x5763a0には同じアドレスが入ってて、配列本体だった。
そして、問題はReturn側。
最初の関数、GetManmothでは、関数から呼び元へ戻る時、アドレスが変わってるのね。そして中身は構造体本体だった。つまり、「関数内で定義できたout変数の中身をコピーして、GetManmoth関数の返送アドレス先に作って、そのアドレスを呼び元に返す」ってことをしてる。
一方のGetJetでは、関数内で定義できたout変数の中身をそのまま返送。そしてこのアドレスの指す中身、なんと、最初に定義した構造体の0x576260から始まる領域から参照している構造体本体のアドレスと一致。
このことから言えるのは、Go言語のプログラムはポインタ渡しで処理する方が、プログラムがコンパクトにまとまるってこと。そして、C言語で開発している人が使う関数と引数とReturn値の考え方そのままでGo言語は大丈夫ってことだね。