データ構造とアルゴリズム(Golang実装)(4)Golang構造とメソッドの簡単な紹介

構造と方法

1.値、ポインタ、参照

これでプログラムができました。

package main

import "fmt"

func main() {
    // a,b 是一个值
    a := 5
    b := 6

    fmt.Println("a的值:", a)

    // 指针变量 c 存储的是变量 a 的内存地址
    c := &a
    fmt.Println("a的内存地址:", c)

    // 指针变量不允许直接赋值,需要使用 * 获取引用
    //c = 4

    // 将指针变量 c 指向的内存里面的值设置为4
    *c = 4
    fmt.Println("a的值:", a)

    // 指针变量 c 现在存储的是变量 b 的内存地址
    c = &b
    fmt.Println("b的内存地址:", c)

    // 将指针变量 c 指向的内存里面的值设置为4
    *c = 8
    fmt.Println("a的值:", a)
    fmt.Println("b的值:", b)

    // 把指针变量 c 赋予 c1, c1 是一个引用变量,存的只是指针地址,他们两个现在是独立的了
    c1 := c
    fmt.Println("c的内存地址:", c)
    fmt.Println("c1的内存地址:", c1)

    // 将指针变量 c 指向的内存里面的值设置为4
    *c = 9
    fmt.Println("c指向的内存地址的值", *c)
    fmt.Println("c1指向的内存地址的值", *c1)

    // 指针变量 c 现在存储的是变量 a 的内存地址,但 c1 还是不变
    c = &a
    fmt.Println("c的内存地址:", c)
    fmt.Println("c1的内存地址:", c1)
}

プリントアウト:

a的值: 5
a的内存地址: 0xc000016070
a的值: 4
b的内存地址: 0xc000016078
a的值: 4
b的值: 8
c的内存地址: 0xc000016078
c1的内存地址: 0xc000016078
c指向的内存地址的值 9
c1指向的内存地址的值 9
c的内存地址: 0xc000016070
c1的内存地址: 0xc000016078

そうa,b変数の値であるが、cポインタ変数は、c1参照変数です。

&変数a:の前に追加された場合、それは変数のメモリアドレスがを指してc := &aいることを意味します。これはポインタ変数です。aca

ポインタが指すメモリの値を取得または設定するときは、ポインタ変数の前に追加してから*、次のような値を割り当てます*c = 4ポインタa指す変数が変わります。

ポインタ変数が別の変数に割り当てられている場合、c1 := c他の変数c1は参照変数と呼ばれ、格納される値はメモリアドレスでもあり、メモリアドレスは変数を指しますa。このとき、参照変数はポインタ変数の単なるコピーであり、2つの変数は相互に独立した。

値変数は値型と呼ばれ、参照変数とポインタ変数は参照型と呼ばれます。

参照型の変数(つまり、ポインター変数)を宣言する方法は?

データタイプの前に1を追加して、次のこと*を示すことができます。

    var d *int

今後は、値のタイプと参照タイプによってのみ変数を区別します。

2.構造

基本的なデータ型では十分ではないGolangため、独自のデータ型、構造を定義できるようにサポートしてください。

// 结构体
type Diy struct {
    A int64   // 大写导出成员
    b float64 // 小写不可以导出
}

構造の名前が定義にDiy使用さtype 结构体名字 structれます。

いくつかのメンバーがありA構造体bには、変数定義、タイプint64、およびfloat64後ろに配置されているように、シンボルを分離する必要はなく、ラップするだけです。構造体の小文字のメンバーは、パッケージの外部では使用できません。つまり、エクスポートすることはできません。

構造を使用する場合:

    // 新建结构体,值
    g := diy.Diy{
        A: 2,
        //b: 4.0, // 小写成员不能导出
    }

    // 新建结构体,引用
    k := &diy.Diy{
        A: 2,
    }

    // 新建结构体,引用
    m := new(diy.Diy)
    m.A = 2

上記で作成した基本データ型に応じた構造を使用できます。

    g := diy.Diy{
        A: 2,
        //b: 4.0, // 小写成员不能导出
    }

値型の構造です。

また、以前の値を加えた構造を使用することができる&か、使用するnew参照構造のタイプが作成され、例えば:

    // 新建结构体,引用
    k := &diy.Diy{
        A: 2,
    }

    // 新建结构体,引用
    m := new(diy.Diy)
    m.A = 2

参照構造と値型構造の違いは何ですか?

関数の内部と外部の変数は独立していることがわかっています。パラメーターが関数に渡されると、パラメーターは値のコピーになります。関数の変数は関数本体で制約されます。関数で渡される変数の値が変更されても、関数の外部では見つかりませんでした。

ただし、参照型の変数は、関数に渡されるときに値で渡されますが、参照型のメモリアドレスはコピーされます。参照はコピーされたと言えます。この参照は、関数の外部の構造体を指します。この参照を関数で使用してください内部の構造の値を変更すると、外部関数も見つかります。

入力構造が参照タイプの構造ではなく値タイプの構造である場合、構造の完全なコピーが作成され、構造は元の構造に関連していません。

組み込みのデータ型スライスsliceと辞書mapは参照型であり、追加の操作を必要としないため、これらの2つの型を関数パラメーターとして渡すことはより危険であり、開発時には注意が必要です。

三、方法

構造は関数にバインドできます。つまり、この関数は構造でのみ使用できます。この関数は構造メソッドと呼ばれます。

// 引用结构体的方法,引用传递,会改变原有结构体的值
func (diy *Diy) Set(a int64, b float64) {
    diy.A = a
    diy.b = b
    return
}

// 值结构体的方法,值传递,不会改变原有结构体的值
func (diy Diy) Set2(a int64, b float64) {
    diy.A = a
    diy.b = b
    return
}

前の関数に基づいfunc Set(a int64, b float64)てになるfunc (diy *Diy) Set(a int64, b float64)だけですが、関数diyでは構造体変数のメンバーを使用できます

上記値型構造を表しdiy Diy使用することができるSet2構造の参照型は、メソッドをdiy *Diy使用することができるSet方法。

この場合、構造体メソッドを使用するたびに、構造体が値であるか参照型であるかに注意を払う必要があります。幸い、Golang私たちは心痛めています。構造体を使用してメソッドが呼び出されるたびに、構造体は自動的に変換されます。メソッドを適合させるため。たとえば、次のとおりです。

    // 新建结构体,值
    g := diy.Diy{
        A: 2,
        //b: 4.0, // 小写成员不能导出
    }

    g.Set(1, 1)
    fmt.Printf("type:%T:%v\n", g, g) // 结构体值变化

    g.Set2(3, 3)
    fmt.Printf("type:%T:%v\n", g, g) // 结构体值未变化

    // 新建结构体,引用
    k := &diy.Diy{
        A: 2,
    }
    k.Set(1, 1)
    fmt.Printf("type:%T:%v\n", k, k) // 结构体值变化
    k.Set2(3, 3)
    fmt.Printf("type:%T:%v\n", k, k) // 结构体值未变化

構造はg値型であり、元々Setメソッドを呼び出すことはできませんが、Golang変換助けを借りて、意味がなくなり、値型は参照型になります。同様に、これkは参照型であり、Set2メソッドは引き続き使用できます

以前、関数は参照で渡され、参照に対応する値は関数内で変更されることも述べました。これも関数の外部で検出されます。

構造法も同じですが、構造自体が範囲内に拡散しており、構造自体をメソッドで変更できますが、構造が値の場合、変更後は外界を見つけることができません。

第三に、新しいキーワードと作るキーワード

キーワードはnew主に参照型構造を作成するために使用され、構造のみを使用できます。

キーワードmakeは、スライスまたは辞書を作成および初期化するために使用されます。直接割り当てることができます:

    e := []int64{1, 2, 3}                 // slice
    f := map[string]int64{"a": 3, "b": 4} // map

しかし、この直接の割り当ては、それを使用するときにデータの場所と量がわからない場合があるため、比較的大雑把です。

したがって、スライスと辞書を作成するときに、容量のサイズを指定できます。例を参照してください:

    s := make([]int64, 5)
    s1 := make([]int64, 0, 5)
    m1 := make(map[string]int64, 5)
    m2 := make(map[string]int64)
    fmt.Printf("%#v,cap:%#v,len:%#v\n", s, cap(s), len(s))
    fmt.Printf("%#v,cap:%#v,len:%#v\n", s1, cap(s1), len(s1))
    fmt.Printf("%#v,len:%#v\n", m1, len(m1))
    fmt.Printf("%#v,len:%#v\n", m2, len(m2))

実行後:

[]int64{0, 0, 0, 0, 0},cap:5,len:5
[]int64{},cap:5,len:0
map[string]int64{},len:0
map[string]int64{},len:0

スライスはmake([],占用容量大小,全部容量大小)定義に使用でき容量サイズのスライスを作成できます5が、実際の占有容量は0、たとえばmake([]int64, 0, 5)5スペースを予約するため、スライスするときにappend、容量不足のためにスペースを内部的に割り当てないため、節約できます。時間。

あなたは、このようなバックなどのパラメータを省略した場合make([]int64, 5)、それは同じでmake([]int64, 5,5)、空容量の全容量は、サイズの大きさに等しいので、。組み込み言語でcapありlen、全容量サイズ、占有容量サイズを表示できます。

同様に、ディクショナリも容量を指定して使用できますが、make([],容量大小)いわゆる占有容量はありません。5つの空白の初期値が必要な場合があるスライスを使用するため、この機能は削除されますが、ディクショナリにキーがない場合は、初期値を予約してください値は影響しません。容量のサイズを省略する0、容量が0のKey-Value構造が作成されます。値を割り当てると、スペースが自動的に割り当てられます。

4番目に、組み込みの構文と関数、メソッドの違い

関数は、関数と構造をバインドすることによってコードフラグメントをカプセル化したものです。

しかし、Golang内蔵の文法一部、機能、ではない方法ではありませんがある、などappend、、 、cap これは文法的な機能です。lenmake

文法機能は高級言語によって提供され、メモリの割り当て方法などの詳細を隠すのに役立ちます。

シリーズ記事エントリー

私は、スター陳思い、私が個人的に書かれているようこそ(Golangが達成)のデータ構造とアルゴリズムの記事で始まる、より親しみやすいGitBookを読むために

元の記事を13件公開しました 賞賛されました0 訪問95

おすすめ

転載: blog.csdn.net/m0_46803965/article/details/105563289