以下のコードは、セマフォを使って(あんま意味ないけど)、同時実行数を制限しているコードで遊んでいたのですが、do関数の引数について疑問が発生したのでメモ。
package main
import (
"context"
"fmt"
"log"
"time"
"golang.org/x/sync/semaphore"
)
func main() {
sem := semaphore.NewWeighted(5)
go do(sem, func() { time.Sleep(1 * time.Second) }, 1)
go do(sem, func() { time.Sleep(1 * time.Second) }, 2)
go do(sem, func() { time.Sleep(1 * time.Second) }, 3)
go do(sem, func() { time.Sleep(1 * time.Second) }, 4)
go do(sem, func() { time.Sleep(1 * time.Second) }, 5)
// go do(sem, func() { time.Sleep(1 * time.Second) }, 6) エラー
time.Sleep(6 * time.Second)
fmt.Println("最高!")
}
func do(sem *semaphore.Weighted, f func(), w int64) { // ここの引数について
if err := sem.Acquire(context.Background(), w); err != nil {
log.Println(err)
return
}
defer sem.Release(w)
switch w {
case 1:
log.Printf("It will definitely come true!")
case 2:
log.Printf("That works!")
case 3:
log.Printf("I did it!")
case 4:
log.Printf("Thank you for this world!")
case 5:
log.Printf("Make the world better!")
case 6:
log.Printf("Do not lose!")
default:
log.Printf("How happy I am!")
}
f()
}
https://github.com/kabasunny/GoPractice/tree/main/semaphore_fanc
このケースでは、func do(sem *semaphore.Weighted, f func(), w int64)となっていて、セマフォは見てわかるように明示的にポインタで受け取るが、関数型の引数は暗黙的に参照で受け取る。
あとついでに、分かったことメモ
・インターフェースを直に実装した関数は作れない
・インターフェースは変数を持てない
・関数は、自身の関数型のみで共有する変数を持てない
・データ型の引数は値(アドレスポインタの値)のコピー渡しが基本で、参照渡しは無い(ただし、スライス、マップ、チャネルなどの一部のデータ型は、内部的には参照型として振る舞うだとぅ!?)
・関数型を引数として渡す場合は参照の値渡しとなる