Golang 言語は関数の戻り値の設計が非常に柔軟で、戻り値は基本的なデータ型に加えて、ポインタ、配列、スライス、構造体などにすることもできます。特に関数の戻り値がポインタ型の場合はさらに注意が必要になるので、この記事で詳しく解説します。
Golang 言語では、関数がポインタ型を返す場合、ローカル変数のアドレスを返さないように注意する必要があります。変数。ローカル変数のライフサイクルは関数内のみであるため、関数が終了すると、ローカル変数が占有していたメモリ空間は再利用されますが、このとき返されたポインタは無効なメモリアドレスを指しているため、再度使用すると問題が発生します。追跡するのが非常に困難です。したがって、関数内で new または make 操作を使用して新しいメモリ空間を割り当て、それを返すことをお勧めします。例:
func foo() *int { var x int = 0 return &x // 错误的返回局部变量地址 } func bar() *int { var x int = 0 return new(int) // 返回新分配的内存地址 }
場合によっては、複数のポインター型の値を一度に返す必要があるかもしれません。ただし、これは必要です。これらのポインターは同じ変数を指すことができないことに注意してください。そうすることで、1 つのポインターが使用されたときに他のポインターが指す値が変化してしまうためです。例:
func foo() (*int, *int) { var x int = 1 return &x, &x // 错误的返回了指向同一个变量的两个指针 } func main() { p1, p2 := foo() fmt.Println(*p1, *p2) // 输出结果为1 1 *p1 = 2 fmt.Println(*p1, *p2) // 输出结果为2 2,p2的值也被改变了 }
したがって、正しいアプローチは、別の変数へのポインターを返すか、それらを構造体型に抽象化して返すことです。
注意が必要なもう 1 つの問題は、ポインタが指す値を関数の外で変更すると予期せぬ問題が発生する可能性があることです。問題。 Golang 言語ではポインタを複数回参照でき、1 つのポインタを複数の変数で指すことができるためです。ポインタが指す値が関数の外で変更されると、ポインタが指すすべての変数も変更されます。例:
func foo() *int { var x int = 1 p := &x return p } func main() { p := foo() q := p *p = 2 fmt.Println(*q) // 输出结果为2,因为q和p指向同一个变量 }
したがって、この状況を回避するには、関数内で new または make 操作を使用して新しいメモリ領域を割り当て、ポインタをその領域にポイントする必要があります。関数の外の変数に影響を与えないように注意してください。
注意すべき最後の問題は、関数で null ポインタが返された場合、A を使用するときです。ポインタを使用するとパニック例外がスローされます。したがって、ポインターを使用する場合は、ポインターが指す値が null でないことを確認する必要があります。そうしないと、例外がトリガーされます。例:
func foo() *int { return nil // 返回了一个空指针 } func main() { p := foo() *p = 1 // 引发panic异常,因为p为空指针 }
したがって、この状況を回避するには、ポインタを使用する前にポインタに対して nil 判定を行う必要があります。
まとめると、関数の戻り値がポインタ型の場合、注意すべき点が多く、慎重に使用する必要があります。そうしないと、さまざまな予期せぬ問題が発生します。したがって、コードを作成するときは、この問題が発生しないように慎重に確認およびテストしてください。
以上がGolang関数の戻り値がポインタの場合の注意事項の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。