言語値、ポインタ、参照型を行きます

オリジナル:https://www.jianshu.com/p/af42cb368cef

-------------------------------------------------- -

CまたはC ++のポインタとポインタは、言語を行く似ていますが、これCまたはC ++プログラムでの潜在的な問題のいくつかを排除し、言語ゴーポインタポインタ演算をサポートしていません。あなたが自由に使用してCまたはC ++の関数のような囲碁の言語を必要とするか、オペレータは削除されませんので、囲碁言語ので、独自のガベージコレクタを持っており、自動的にメモリを管理します。

参考文献は、創造の囲碁言語の後にJavaやPythonのオブジェクトポインタのように使用することができます。

関数やメソッドに渡された値のコピー、およびこの機能または重複した値を用いた方法になります。ただし、移動中、またはブール変数または数値型や文字列型の配列に値によって渡されます、それは元の値には影響しません。一般的に、それは非常に安価である値で渡さブール変数または数値型や文字列型のため、転写プロセスにおける安全性を最適化するために、言語コンパイラを移動します。

しかし、移動中に、文字列は不変であるため、変更された文字列(例えば、+ =演算子)の間に、移動に新しい文字列を作成し、元の文字列をコピーし、新規に追加する必要があります文字列の後、大規模な文字列のために、操作のコストが比較的大きいかもしれません。

大規模な文字列の場合は、同様の配列に渡された値です。発生する可能性が莫大なコストに対処するためには、代わりにスライス配列の配列を使用しての言語を移動します。かかわらず、スライスまたはどのくらいの容量の長さの、同じ文字列のセクションでライン上の転送を送信します。スライスが可変であるため、セクションが変更されたコピー操作は、文字列などの新しいスライスを作成する必要はありません、参照型です。

func main() {
   a := 3 b := 4 c := "abc" d := [3]int{1,2,3} fmt.Printf("main方法:a的值为 %v,b的值为 %v,c的值为 %v,d的值为 %v \n",a,b,c,d) demo(a,b,c,d) fmt.Printf("main方法:a的值为 %v,b的值为 %v,c的值为 %v,d的值为 %v \n",a,b,c,d) } func demo(a,b int,c string,d [3]int) { a = 5 b = 6 c = "efg" d[0] = 0 fmt.Printf("demo函数:a的值为 %v,b的值为 %v,c的值为 %v,d的值为 %v\n",a,b,c,d) } ----output---- main方法: a的值为 3,b的值为 4,c的值为 abc,d的值为 [1 2 3] demo函数: a的值为 5,b的值为 6,c的值为 efg,d的值为 [0 2 3] main方法: a的值为 3,b的值为 4,c的值为 abc,d的值为 [1 2 3] 

移動言語参照タイプは、マッピング(地図)、配列スライス(スライス)、チャネル(チャネル)、およびメソッド関数。

移動ガベージコレクタが存在するので、ローカル変数がもはや使用されている(もはや範囲に作用するように呼ぶかどうか)に彼らの範囲によってガベージオフ収集し、ローカル変数のライフサイクルとなり決断。私たちは、ローカル変数のライフサイクルにそれを管理したい場合は?そして、あなたが変数に少なくともポインタがある限り、ローカル変数を管理するためにポインタを使用する必要があり、その変数のライフサイクルは、スコープの独立することができます。

変数は、私たちはライフサイクルを制御することを可能にするポインタを使用して、他の変動費の範囲によって影響を受けませんが配送中に最小化され、その内容は簡単ではなく、コピー操作の値よりも、変数を変更することができます。ポインターは、実際に別の変数のメモリアドレスを保持する変数であり、任意の変数は、コンテンツポインタにより変更することができるメモリアドレスを保存するためのポインタです。渡すポインタは非常に安いです。

ポインタを使用する前に、我々は2つの演算子の意味を理解する必要があり
単項演算子、変数メモリのリターンアドレスとして使用された場合、バイナリ演算子、ビット単位のAND演算として:①演算子&を。
②演算子*:バイナリ演算子として使用される乗算演算である場合に単項演算子(間接参照演算子)、ポインタ変数の戻り値として、実際には、解放ポインタ参照変数変数の値を返します。

ポインタを作成して使用して、コードは以下の実施例に見ることができます

func main() {
   a := 3 p := &a //这里是获取变量a的内存地址,并将其赋值给变量p fmt.Printf("a的值为 %v, a的指针是 %v ,p指向的变量的值为 %v\n",a,p,*p) } -----output----- a的值为 3, a的指针是 0xc042060080 ,p指向的变量的值为 3 

変数aの値は、二つの交換に使用することができ、等しい同一のメモリアドレスに関連付けられているどちらも実際には、* pと、動作を変更する変数の一つは、別の変数の値に影響を与えるが、変数pがある場合死ぬために、他の変数のポインタ代入。

ポインタの統合利用については、我々は次のコード例を見て

func main() {
   a := 3 b := 4 p1 := &a //获取变量a的内存地址,并将其赋值给变量p1 p2 := &b //获取变量b的内存地址,并将其赋值给变量p2 fmt.Printf("a的值为 %v, a的指针是 %v ,p1指向的变量的值为 %v\n",a,p1,*p1) fmt.Printf("b的值为 %v, b的指针是 %v ,p2指向的变量的值为 %v\n",b,p2,*p2) fmt.Println(demo(p1,p2)) fmt.Printf("a的值为 %v, a的指针是 %v ,p1指向的变量的值为 %v\n",a,p1,*p1) fmt.Printf("b的值为 %v, b的指针是 %v ,p2指向的变量的值为 %v\n",b,p2,*p2) } func demo(a,b *int)int { *a = 5 *b = 6 return *a * *b //这里出现连续的两个*,Go编译器会根据上下文自动识别乘法与两个引用 } -----output----- a的值为 3, a的指针是 0xc042060080 ,p1指向的变量的值为 3 b的值为 4, b的指针是 0xc042060088 ,p2指向的变量的值为 4 30 a的值为 5, a的指针是 0xc042060080 ,p1指向的变量的值为 5 b的值为 6, b的指针是 0xc042060088 ,p2指向的变量的值为 6 

コードは、上記によれば、我々はポインタを見ることができた後に、整数型の値は、元々関数またはメソッドの値に影響を与える元の変数に変更を渡します。

ヌルポインタ
ポインタが定義された変数のいずれにも割り当てられていない場合、その値はゼロです。
NULLポインタは、NULLポインタと呼ばれています。
コンセプトのようにNULL nullをゼロと他の言語、なし、nilは、すべてがゼロ値またはNULL値を参照してください。
次の例を確認します。

package main

import "fmt"
func main() { var ptr *int fmt.Printf("ptr 的值为 : %x\n", ptr ) } 

上記の出力例です。

ptr 的值为 : 0

NULLポインタの分析:

if(ptr != nil)     /* ptr 不是空指针 */
if(ptr == nil) /* ptr 是空指针 */ 

複数の間接参照
の例として上記のコードに、:= 3、P1:= & 媒体は、点P1は点P1 P2メモリアドレスがある場合、間接参照と呼ばれるメモリアドレス、点p1であります変数の一つは、操作の内容を変更する場合は、メモリアドレスが、これはすべての変数の他のコンテンツに影響を与えます、参照の種類に関係なく、複数の間接と呼ばれていません。

func main() {
   a := 3 p1 := &a //p1是指向变量a内存地址的指针 p2 := &p1 //p2是指向变量p1内存地址的指针 fmt.Printf("a:%v, p1:%v, *p1:%v, p2:%v, **p2:%v\n",a,p1,*p1,p2,**p2) a = 4 fmt.Printf("a:%v, p1:%v, *p1:%v, p2:%v, **p2:%v\n",a,p1,*p1,p2,**p2) } -----output----- a:3, p1:0xc0420080b8, *p1:3, p2:0xc042004028, **p2:3 a:4, p1:0xc0420080b8, *p1:4, p2:0xc042004028, **p2:4 

演算子&を使用して新しい機能
ゴー言語は、変数を作成する2つの方法を提供し、それらへのポインタを取得することができます。新しい機能と&演算子。これら2つのコードの使用は、以下に示すように

type Person struct {
   name string
   sex  string
   age int } func main() { person1 := Person{"zhangsan","man",25} //创建一个person1对象 person2 := new(Person)//使用new创建一个person2对象,同时获得person的指针 person2.name,person2.sex,person2.age = "wangwu","man",25 person3 := &Person{"lisi","man",25}//使用&创建一个person3对象,同时获得person的指针 fmt.Printf("person1:%v, person2:%v, person3:%v\n",person1,person2,person3) } -----output----- person1:{zhangsan man 25}, person2:&{wangwu man 25}, person3:&{lisi man 25} 

2つの方法で結果、出力、および新しい新機能&演算子とは大きく異なる、&演算子よりコンパクト作成し、常に属性の初期値を指定することができます。ゴーポインタ人、人で印刷属性の具体的な内容を印刷し、プレフィックスに追加&変数を示すときはポインタです。

次に、我々は構造体へのポインタを渡し、構造体のプロパティを変更し、言語がどのように動作するかを見に行きます。

type Person struct {
   name string
   sex  string
   age int } func main() { person1 := Person{"zhangsan","man",25} //创建一个person1对象 fmt.Printf("person1:%v\n",person1) demo(&person1) fmt.Printf("person1:%v\n",person1) } func demo(person *Person) { (*person).age = 18 //显示的解引用 person.name = "GoLang" //隐式的解引用 } 

Pserson1オブジェクトを使用すると、道、最初の(つまり、元のオブジェクトへのポインタである)2つのデモ関数間接参照がある見ることができ、機能をデモするために、そのポインタの後に初期化プロパティを設定し、メイン関数を作成するには(*人).age溶液は、参照により示されている、第二のオペレータは、自動的に逆参照されます使用して、差がないの使用が、第二の両方が簡単です。「」



著者:ハッピーアワージル
リンクします。https://www.jianshu.com/p/af42cb368cef
出典:ジェーン・ブック
著者によって予約ジェーンブックの著作権、いかなる形で再現され、承認を得るために、作者に連絡して、ソースを明記してください。

おすすめ

転載: www.cnblogs.com/oxspirt/p/10941480.html