Go結構體與方法

1、排序算法之go實現golang

1.冒泡排序算法

func bubbleSort(slice []int){
    for i := 0; i < len(slice); i++{
        ctn := 0
        for j := 0; j < len(slice) - i - 1; j++{
            if slice[j] > slice[j+1]{
                slice[j], slice[j+1] = slice[j+1], slice[j]
                ctn ++
            }
        }
        if ctn == 0{
            break
        }
    }
}

func main(){
    slice := []int{2,6,4,3,1,7,9,12,31,15}
    bubbleSort(slice)
    fmt.Println(slice)
}
View Code

2.選擇排序json

func selectSort(slice []int){
    var min_ind int
    for i := 0; i < len(slice); i++{
        min_ind = i
        for j := i + 1; j < len(slice); j++{
            if slice[j] < slice[min_ind]{
                slice[j], slice[min_ind] = slice[min_ind], slice[j]
            }
        } 
    }
}

func main(){
    slice := []int{2,6,4,3,1,7,9,12,31,15}
        selectSort(slice)
    fmt.Println(slice)
}
View Code

3.插入排序數據結構

func insertSort(slice []int){
    for i := 1; i < len(slice); i++{
        for j := i; j > 0; j--{
            if slice[j] > slice[j - 1]{
                break
            }
            slice[j], slice[j - 1] = slice[j - 1], slice[j]
        }
    }
}

func main(){
    slice := []int{2,6,4,3,1,7,9,12,31,15}
    insertSort(slice)
    fmt.Println(slice)
}
View Code

4.快速排序ide

func quickSort(slice []int, first int, last int){
    if first >= last{
        return
    }
    mid_val := slice[first]
    low := first
    high := last
    for low < high{
        for (low < high && slice[high] >= mid_val){
            high--
        }
        slice[low] = slice[high]
        for (low < high && slice[low] <= mid_val){
            low++
        }
        slice[high] = slice[low]
    }
    slice[low] = mid_val
    quickSort(slice, first, low - 1)
    quickSort(slice, high + 1, last)
}

func main(){
    slice := []int{2,6,4,3,1,7,9,12,31,15}
    quickSort(slice, 0, len(slice) - 1)
    fmt.Println(slice)
}
View Code

2、go中的struct函數

1.用來自定義複雜數據結構佈局

2.struct裏面能夠包含多個字段(屬性)ui

3.struct類型能夠定義方法(注意和函數的區分)this

4.struct類型是值類型spa

5.struct類型能夠嵌套

6.go語言沒有calss類型,只有struct類型

struct的定義

1.struct聲明

type 標識符 struct{
  field1 type
  field2 type }

2.struct中字段訪問,和其它語言同樣,使用點

3.struct定義的三種形式

var stu Student

var stu *Student = new(Student)

var stu *Student = &Student{}

//其中b和c返回的都是指向結構體的指針,訪問形式以下:
(*stu).Name,能夠簡寫成stu.Name

4.struct的內存佈局:struct中的全部字段在內存中是連續的,佈局以下:

type Student struct{
    Name string
    Age int
}

func main(){
    var stu1 = Student{
        Name: "bob",
        Age: 18,
    }
    var stu2 Student
    stu2.Name = "tony"
    stu2.Age = 18
    fmt.Println(stu1)
    fmt.Println(stu2)
    fmt.Println(stu1.Name)
    fmt.Printf("addr:%p\n",&stu1.Name)
    fmt.Printf("addr:%p\n",&stu1.Age)
}
View Code

鏈表定義

每一個節點包含下一個節點的地址,一般把鏈表中的第一個節點叫作鏈表頭

type Student struct{
    Name string
    Next *Student
}
type Student struct{
    Name string
    Age int
    Next *Student
}
func trans(p *Student){
    for p != nil{
        fmt.Println(*p)
        p = p.Next
    }
}


func main(){
    head := Student{
        Name: "b1",
        Age: 18,
    }

    stu1 := Student{
        Name: "b2",
        Age: 32,
    }

    head.Next = &stu1
    trans(&head)
}
鏈表實現
package main

import "fmt"

type Student struct{
    Name string
    Age int
    Next *Student
}

func forAppend(p *Student, n int){
    tail := p
    for i := 0; i < n; i++{
        stu := Student{
            Name: fmt.Sprintf("b%d",i),
            Age: 19 + i,
        }
        tail.Next = &stu
        tail = &stu
    }
}

func trans(p *Student){
    for p != nil{
        fmt.Println(*p)
        p = p.Next
    }
}

func main(){
    head := Student{
        Name: "b",
        Age: 18,
    }    
    
    forAppend(&head,10)
    trans(&head)
}
循環後插
package main

import "fmt"

type Student struct{
    Name string
    Age int
    Next *Student
}

func forInsert2(p *Student, n int) *Student{
    for i := 0; i < n; i++{
        stu := Student{
            Name: fmt.Sprintf("b%d",i),
            Age: 19 + i,
        }
        stu.Next = p
        p = &stu
        //只是更改了指針的副本
    }
    return p 
}
func trans(p *Student){
    for p != nil{
        fmt.Println(*p)
        p = p.Next
    }
}

func main(){
    head := Student{
        Name: "b",
        Age: 18,
    }    
    p := forInsert2(&head, 10)
    trans(p)
}
循環頭插1
package main

import "fmt"

type Student struct{
    Name string
    Age int
    Next *Student
}

func forInsert1(p **Student, n int){
    //傳入指針的地址
    for i := 0; i < n; i++{
        stu := Student{
            Name: fmt.Sprintf("b%d",i),
            Age: 19 + i,
        }
        //更改指針的地址
        stu.Next = *p
        *p = &stu
    }
}

func trans(p *Student){
    for p != nil{
        fmt.Println(*p)
        p = p.Next
    }
}

func main(){
    // head := Student{
    //     Name: "b",
    //     Age: 18,
    // }    
    // p := forInsert2(&head, 10)
    // trans(p)
    var head *Student = new(Student)
    head.Name = "b"
    head.Age = 18
    forInsert1(&head, 10)
    trans(head)
}
循環頭插2
//刪除屬性Name爲b8的節點

func del(p *Student, name string){
    prev := p
    for p != nil{
        if p.Name == name{
            prev.Next = p.Next
        }
        prev = p
        p = p.Next
    }
}

//沒法刪除頭節點

//改寫
func del(p **Student, name string){
    //前一個節點
    var prev *Student
    //當前節點
    cur := *p
    for cur != nil{
        if cur.Name == name{
            //若是是刪除頭節點,就更改頭節點的地址
            if cur == *p{
                *p = (*p).Next
            }else{
                prev.Next = cur.Next
            }
            break
        }
        prev = cur
        cur = cur.Next
    }
}

func main(){
    var head *Student = new(Student)
    head.Name = "b"
    head.Age = 18
    forInsert1(&head, 10)
    del(&head, "b8")
    trans(head)
}
刪除指定節點

雙鏈表的定義

兩個指針分別指向前一個節點和後一個節點

type Student struct{
    Name string
    Next *Student
}

二叉樹定義:

兩個指針分別指向左子樹和右子樹

type Student struct{
    Name string
    Left *Student
    Right *Student
}    
//二叉樹

package main

import "fmt"

type Student struct{
    Name string
    Age int
    Left *Student
    Right *Student
}
func trans(root *Student){
    if root == nil{
        return
    }
    fmt.Println(root.Name)
    trans(root.Left)
    trans(root.Right)
}

func main(){
    var root = new(Student)
    root.Name = "stu0"
    root.Age = 18

    var left01 = new(Student)
    left01.Name = "stu1"
    left01.Age = 20

    var right01 = new(Student)
    right01.Name = "stud2"
    right01.Age = 25

    var right02 = new(Student)
    right02.Name = "stud3"
    right02.Age = 30

    root.Left = left01
    root.Right = right01
    right01.Left = right02

    trans(root)
}
View Code

 5.結構體是用戶單獨定義的類型

type integer int
var i integer = 1
var j int = 2
//i,j是屬於不一樣類型
package main

import "fmt"

type myInt int

func main(){
    var a myInt = 10
    var b int = 20
        //編譯不經過,a和b是不一樣的類型
    a = b
    fmt.Println(a)
}    

func main(){
    var a myInt = 10
    var b int = 20
    //須要強制轉換
    a = myInt(b)
    fmt.Println(a)
}
View Code

golang沒有構造函數,可使用工廠模式解決這個問題

package model
type Student struct{
    Name string
    Age int
}
func NewStudent(name string, age int)*student{
    return &student{
        Name: name
        Age: age
    }
}

packeage main
//s := new(Student)
s := model.NewStudent("tony",20)
View Code

6.struct中的tag

咱們能夠爲struct中的每一個字段,寫上一個tag,這個tag能夠經過反射的機制獲取到,最經常使用的場景就是json的序列化與反序列化

type Student struct{
    Name string "this is name field"
    Age int    "this is age field"
}
package main

import (
    "fmt"
    "encoding/json"
)

type Student struct{
    Name string `json:"name"`
    Age int `json:"age"`
}

func main(){
    stu := Student{
        Name: "bob",
        Age: 18,
    }
    data, err := json.Marshal(stu)
    if err != nil{
        fmt.Println("json encode faile")
        return
    }
    fmt.Println(string(data))
}
View Code

7.結構體中字段能夠沒有名字,即匿名字段

type Train struct{
    Car
    Start time.Time
    int
}
package main

import "fmt"

type Student struct{
    Name string
    Age int
}

type Class struct{
    Name string
    Student
}


func main(){
    var c1 Class
    //當結構體中有該字段,直接訪問
    c1.Name = "T1"
    //經過類型點的方式訪問匿名字段
    c1.Student.Name = "bob"
    c1.Student.Age = 18
    //不能同時出現相同類型的兩個匿名字段
    fmt.Println(c1)
}
View Code

方法

golang中的方法是做用在特定類型的變量上,所以自定義類型均可以有方法,不單單是struct

1.定義

func(recevier type) methodName(參數列表)(返回值列表){

}
type Student struct{
    Name string
    Age int
}

//this就是stu,init爲方法名
func (this *Student) init(name string, age int){
    this.Name = name
    this.Age = age
}

func main(){
    var stu Student
}
View Code

2.方法的調用

func (this *Student) init(name string, age int){
    this.Name = name
    this.Age = age
}

func main(){
    var stu Student
    //其實本質是(&stu).init("bob", 18),go作了簡化
    stu.init("bob", 18)
    fmt.Println(stu)
}

3.指針receiver和值receiver:本質上和函數的值傳遞和地址傳遞是同樣的

4.方法的訪問控制,經過大小寫控制

5.繼承:若是一個struct嵌套了另外一個匿名結構體,那麼這個結構體能夠直接訪問匿名結構體的方法,從而實現繼承;組合:若是一個struct嵌套了另外一個有名結構體,那麼這個模式就叫作組合

package main

import "fmt"

type Animal struct{
    Name string
}

func (this Animal) Speak(){
    fmt.Printf("%v正在咆哮...\n",this.Name)
}

type Dog struct{
    Animal
}

type Zoo struct{
    Name string
    D Dog
}

func main(){
    var d1 Dog
    d1.Name = "大黃"
    d1.Speak()
    var zoo Zoo
    zoo.Name = "1th"
    zoo.D.Speak()
}
View Code

6.多重繼承:若是一個struct嵌套了多個匿名結構體,那麼這個結構體能夠直接訪問多個匿名結構體的方法,從而實現了多重繼承

接口實現String():

若是一個變量實現了String()這個方法,那麼fmt.Printf默認會調用這個變量的String()進行輸出

package main

import "fmt"

type Animal struct{
    Name string
}

func (this Animal) String() string{
    str := fmt.Sprintf("name=[%s]",this.Name)
    return str
}

type Dog struct{
    Animal
}

func main(){
    var d1 Dog
    d1.Name = "大黃"
    fmt.Printf("%s",d1)
}
View Code
相關文章
相關標籤/搜索