最終更新日: 2026-07-25
TOP(About this memo)) > 一覧(Go) > 関数・レシーバー
package main
import "fmt"
func main() {
test := "aaaa"
fmt.Println(test) //aaaa
b := func() {
test := "bbbb" // :=ではなく=にすると外部のtestを変更する。
fmt.Println(test) //bbbb
}
b()
fmt.Println(test) //aaaa
}
func a() {
b := func() {}
b()
//func c() {} //ただし、これはシンタックスエラーとなる。
//c()
}
func Query(db *sql.DB, args ...any) {
...
if len(args) ...
}
opts := []cmp.Option{
cmpopts.IgnoreFields(entity.User{}, "", ""),
}
if diff := cmp.Diff(want, respObj, opts...); diff != "" {// 配列を可変長引数として展開
t.Errorf("Compare value is mismatch (-v1 +v2):%s\n", diff)
}
func Split(s string, pos int) (string, string) {
return s[0:pos], s[pos:]
}
func Join(s, t string) string {
return s + t
}
if Join(Split(value, len(value)/2)) != value {
log.Panic("test fails")
}
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
import "fmt"
func main() {
f(func() {
defer fmt.Println("callback end")
fmt.Println("callback")
})
}
func f(a func()) {
a()
fmt.Println("f end")
}
/*
callback
callback end
f end
*/
func main() {
defer println("5")
{
defer println("4") // 囲んでいるブロックスコープの末尾ではなく、関数(main関数)の最後に実行される。
println("1")
}
defer println("3")
println("2")
}
/// 1 -> 2 -> 3 -> 4 -> 5
var (
// std is the name of the standard logger in stdlib `log`
std = New()
)
func (v Vertex) Abs() float64 { /// <- この (v Vertex) で指定している箇所をレシーバーという
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs())
}
func (p Person) Greet(msg string) {
// ...
}
// 実は、これは下記と等価らしい。
func Person.Greet(p Person, msg string) {
// ...
}
import (
"encoding/json"
"reflect"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
// func GetFirst[A any](a A, b ...any) A {
// return a
// }
// func GetLast(a ...any) any {
// return a[len(a)-1]
// }
// func UnmarshalString[S any](jsn string, to *S) (*S, error) {
// if err := json.Unmarshal([]byte(jsn), to); err != nil {
// return nil, err
// }
// return to, nil
// }
func Ptr[T any](a T) *T {
return &a
}
func TestReciever(t *testing.T) {
t.Run("assert_reciver", func(t *testing.T) {
assert.Exactly(t, time.Time{}.IsZero(), true)
assert.Exactly(t, Ptr(time.Time{}).IsZero(), true)
assert.Exactly(t, Ptr(time.Now()).IsZero(), false)
assert.Exactly(t, testStruct1("").valueReciever(), true)
assert.Exactly(t, testStruct1("").pointerReciever(), true) //値型のレシーバーじゃなくても呼べる。
assert.Exactly(t, Ptr(testStruct1("")).valueReciever(), true) //ポインタ型のレシーバーじゃなくても呼べる。
assert.Exactly(t, Ptr(testStruct1("")).pointerReciever(), true)
// 値レシーバーを実装していると、そのポインターも実装していることになる。
// しかし、ポインタレシーバーを実装しているときは、その値は実装していることにならない。
_, ok := reflect.ValueOf(time.Time{}).Interface().(json.Marshaler)
assert.Exactly(t, ok, true)
_, ok = reflect.ValueOf(&time.Time{}).Interface().(json.Marshaler)
assert.Exactly(t, ok, true)
_, ok = reflect.ValueOf(time.Time{}).Interface().(json.Unmarshaler)
assert.Exactly(t, ok, false) // これはfalseになる
_, ok = reflect.ValueOf(&time.Time{}).Interface().(json.Unmarshaler)
assert.Exactly(t, ok, true)
})
}
type testStruct1 string
func (t testStruct1) valueReciever() bool {
return true
}
func (t testStruct1) pointerReciever() bool {
return true
}
type s1 struct {
f1 string
}
func (s s1) set() {
s.f1 = "aaaa"
}
func (s *s1) set2() {
s.f1 = "bbbb"
}
func main() {
v1 := s1{f1: "0000"}
v1.set()
fmt.Println(v1.f1)//0000
(&v1).set2()
fmt.Println(v1.f1)//bbbb
}
p := &json.UnmarshalTypeError{}
fmt.Println(errors.As(json.Unmarshal([]byte("{"), &struct{}{}), &p))
In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution. The return parameters of the function are passed by value back to the caller when the function returns.
package main
import "fmt"
func main() {
// スライスは参照だが、関数へ渡したスライスの参照先を変更すると、ポインタ自体が置き換わり、元の参照先は変わらない仕様となっている。
a := []string{}
fmt.Printf("before call: %p\n", a)
fmt.Println(a)
f(a)
fmt.Printf("after call: %p\n", a)
fmt.Println(a)
fmt.Println("_______")
// mapは参照であり、関数へ渡したmapの参照先を変更すると、元の参照先も変わる。
b := map[string]string{}
fmt.Printf("before call: %p\n", a)
fmt.Println(b)
f2(b)
fmt.Printf("after call: %p\n", a)
fmt.Println(b)
fmt.Println("_______")
// 配列の場合は参照でないため、関数側に渡した値を変更しても元の値は変わらない。
c := [3]string{"a", "b", "c"}
fmt.Println(c)
f3(c)
fmt.Println(c)
fmt.Println("_______")
}
func f(a []string) {
fmt.Printf("before append %p\n", a)
a = append(a, "a")
fmt.Printf("after append %p\n", a)
}
func f2(a map[string]string) {
fmt.Printf("before append %p\n", a)
a["a"] = "a"
fmt.Printf("after append %p\n", a)
}
func f3(a [3]string) {
a[2] = "a"
}
/*
before call: 0x590360
[]
before append 0x590360
after append 0xc000014070
after call: 0x590360
[]
_______
before call: 0x590360
map[]
before append 0xc0000160f0
after append 0xc0000160f0
after call: 0x590360
map[a:a]
_______
[a b c]
[a b c]
_______
*/