Tinywan Golang Tutorial Versions Save

:bouquet: Golang 系列教程(译)

v2.1

3 years ago

update

v2.0

6 years ago

Map

函数

结构体

Go语言结构体

package main

import "fmt"

const (
    MethodGet     = "GET"
    MethodHead    = "HEAD"
    MethodPost    = "POST"
    MethodPut     = "PUT"
    MethodPatch   = "PATCH" // RFC 5789
    MethodDelete  = "DELETE"
    MethodConnect = "CONNECT"
    MethodOptions = "OPTIONS"
    MethodTrace   = "TRACE"
)

type Person struct {
	Name    string
	Age     int
	Contact struct {
		Phone, City string
	}
}

// 组合的使用,嵌入结构的使用,被嵌入的结构体相当于把自己所有属性给予了需要嵌入的结构体中
type Hourman struct {
	Sex int
}

type Teacher struct {
	Hourman // 继承 Hourman 所有
	Name string
	Age int
}

type Student struct {
	Hourman // 继承 Hourman 所有
	Name string
	Age int
}


func main() {
	sr1 := Person{}
	fmt.Println(sr1)

	sr2 := Person{}
	sr2.Name = "Tinywan"
	sr2.Age = 24
	fmt.Println(sr2)

	sr3 := Person{
		Name: "Tinywan Default",
		Age:  25,
	}
	fmt.Println(sr3) // {Tinywan Default 25}
	A(sr3)           // 传递值 {A Tinywan 25}
	fmt.Println(sr3) // {Tinywan Default 25}

	//传递指针
	sr4 := Person{
		Name: "Tinywan Default",
		Age:  25,
	}
	fmt.Println(sr4) // {Tinywan Default 25}
	B(&sr4)          // 传递地址 &{Pointer B 25}
	fmt.Println(sr4) // {Pointer B 25}

	// 一般在结构体初始化的时候进行【取地址符号】,这时候被赋值的变量将会直接指向结构体的【指针】
	// 【推荐改写法】
	sr5 := &Person{ // 这里直接取地址
		Name: "Default",
		Age:  24,
	}
	fmt.Println("Update Before :", sr5)
	sr5.Name = "Update"
	B(sr5)
	C(sr5)
	fmt.Println("Update After :", sr5)

	// 匿名
	sr6 := &struct {
		Name string
		Age  int
	}{
		Name: "nothing",
		Age:  26,
	}
	fmt.Println("%v %p", sr6, sr6)

	//匿名结构使用
	sr7 := Person{Name: "Name01", Age: 24}
	sr7.Contact.Phone = "13669361192"
	sr7.Contact.City = "GanSu"
	fmt.Println(sr7)

	// 赋值操作
	sr8 := Person{Name: "Name008", Age: 26}
	var b Person // 这里必须声明为为Person的类型
	b = sr8
	fmt.Println(sr8) // {Name008 26 { }}
	fmt.Println(b) // {Name008 26 { }}

	// 嵌入和组合的使用
	te := Teacher{Name:"Student Teacher", Age:48, Hourman: Hourman{Sex: 1}} //初始化操作
	st := Student{Name:"Wan Student", Age:24, Hourman: Hourman{Sex: 2}}
	// update
	te.Name = "2018 Name"
	te.Age = 12
	te.Sex = 0
	fmt.Println(te,st) // {{0} 2018 Name 12} {{2} Wan Student 24}

}

// 传值引用
func A(person Person) {
	person.Name = "A Tinywan"
	fmt.Println(person) // {A Tinywan 25}
}

//
func B(person *Person) {
	person.Name = "Pointer B "
	fmt.Println(person)
}

func C(person *Person) {
	person.Name = "Pointer C "
	fmt.Println(person)
}

v1.0

6 years ago

数组

深入解析 Go 中 Slice 底层实现

方式一、创建(定义)数组

数组在Go中是值类型,而不是引用(其他语言的数组则是引用类型) PS:切片(slice)是一个引用类型 数组不是统一的类型,大小不同的数组是不可以比较的 不同数组类型是不可以比较的

var a[2]int
var b[3]string

// 提前知道数组中的值
var a[2]int{11,22}
var a[20]int{19:11} // 索引值为19的元素赋值为 11 ,其他的默认为 0

// 不指定数组的长度 ...
var c = [...]int{11,22,33,44}
var d = [...]int{19:90} // 尽可能的满足索引值得数组

指向数组的指针和指向指针的数组

//定义数组a
a := [...]int{19:100}

// 指向数组的指针
var p *[20]int = &a  //长度为20的int型数组,这里的数组长度`20`必须和a数组长度相等
fmt.Println(p) //以上表示取这样一个数组的地址 
// 打印结果:&[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19]

//指向指针的数组
x , y  := 1, 2
pp := [...]*int{&x,&y} // 指向int型的指针,保存的元素是指向int型的指针。输出x,y的地址:
fmt.Println("pp is ",pp)  // 打印结果:pp is  [0xc420012128 0xc420012130]

new 创建一个数组

 ppp := new([10]int)
fmt.Println("----ppp-------",ppp); //输出结果:`&[0 0 0 0 0 0 0 0 0 0]` 
//以上为指向数组的指针

两种方式修改数组赋值

// 第一种方式
n := [10]int{}
n[1] = 10
fmt.Println("-----1------",n)  // 输出:`[0 10 0 0 0 0 0 0 0 0]`

// 第二种方式
m := new([10]int)
m[1] = 20
fmt.Println("-----2------",m)  // 输出:`&[0 20 0 0 0 0 0 0 0 0]`

多维数组

arr := [2][3]int{
                {1, 2, 3},
                {4, 5, 6}} //最外面的`}`不可以换行的,否则报错:`syntax error`
fmt.Println("-----",arr)

冒泡排序

第一种写法

func main(){
        a :=[...]int64{12,23,293,34,128,132}
        fmt.Println(a)
        num := len(a)
        for i := 0; i<num; i++ {
                for j := i+1; j<num; j++ {
                        if a[i]<a[j] {
                                tmp := a[i]
                                a[i] = a[j]
                                a[j] = tmp
                        }
                } 
        }
        fmt.Println(a)
}

从大到小排序

第二种写法

func main(){
        a :=[...]int64{12,23,293,34,128,132}
        fmt.Println(a)
        num := len(a)
        for i := 0; i<num; i++ {
                for j := i+1; j<num; j++ {
                        if a[i]<a[j] {
                                a[i],a[j] = a[j],a[i]
                        }
                } 
        }
        fmt.Println(a)
}

切片

package main

import "fmt"

func main() {
	a := [10]int{1,2,3,4,5,6,7,8,9}
	var s1  []int
	fmt.Println(s1) // 输出:[]

	// 只取一个元素
	s2 := a[5]
	fmt.Println(s2) // 输出:6

	// 只取前5个元素
	s3 := a[:5]
	fmt.Println(s3) // 输出:[1 2 3 4 5]

	// 只取后5个元素
	s4 := a[5:]
	fmt.Println(s4) // 输出:[6 7 8 9 0]

	// 截取某一段元素,不包括最后一个
	s5 := a[5:8]
	fmt.Println(s5) // 输出:[6 7 8]

	// 使用make创建一个切片
	s6 := make([]int, 3, 10) //  func make([]T, len, cap) []T 可以用来创建切片
	fmt.Println(len(s6),cap(s6));

	s7 := []byte{'a','b','c','d','e','f','g','h','i','j','k'} // 切片底层对应的数组

	slice_a := s7[2:5]
	fmt.Println(slice_a) //	输出的assica码 值 [99 100 101]
	fmt.Println(string(slice_a)) // 格式化为字符串输出
	fmt.Println(len(slice_a),cap(slice_a))

	slice_b := s7[3:5]
	fmt.Println(string(slice_b)) // 格式化为字符串输出

	// append 函数使用
	s8 := make([]int, 3, 6) // 3个元素,容量为6的切片
	fmt.Printf("%p\n", s8)  // 打印内存地址:0xc042074030
	s8 = append(s8, 12, 48)
	fmt.Printf("%v %p", s8, s8) // 格式化打印值和内存地址:[0 0 0 12 48] 0xc042074030

	// 追加的元素如果没有超多切片容量,则切片的地址是不变的,否则内存地址会变
	s8 = append(s8, 66, 88)
	fmt.Printf("%v %p\n", s8, s8) // [0 0 0 12 48 66 88] 0xc042048060

	// copy 使用
	s9 := []int{1,2,3,4,5,6,7}
	s10 := []int{33,44,55}
	copy(s9,s10) // copy(拷贝,被拷贝)
	fmt.Println(s9) //[33 44 55 4 5 6 7]

	copy(s10,s9) 
	fmt.Println(s10) // [33 44 55]

	copy(s9[2:4],s10[0:2]) 
	fmt.Println(s9) // [1 2 33 44 5 6 7]

	s11 := s7[:]
	fmt.Println(s11) // copy一个数组的所有
}

Map(集合)

package main

import (
	"fmt"
	"sort"
)

func main(){
	// 方式一
	var m map[int]string // 声明一个map
	fmt.Println(m)
	m = map[int]string{} // 初始化一个map
	fmt.Println(m)

	// 方式二
	var m2 map[int]string = map[int]string{}
	fmt.Println(m2)

	// 方式三
	m3 := map[int]string{}
	fmt.Println(m3)

	// 设置、获取、删除
	m3[1] = "Tinywan"
	a := m3[1]
	fmt.Println(m3) // map[1:Tinywan]
	fmt.Println(a)  // Tinywan

	delete(m3,1)  // 删除一个map
	fmt.Println(m3) // map[]

	// 复杂map 的操作
	var m5 map[int]map[int]string // 定义
	m5 = make(map[int]map[int]string) // 通过 make 初始化 最外层的 map
	
	m5[1] = make(map[int]string) // 针对外层value 的map进行初始化
	m5[1][1] = "OK"
	m_a := m5[1][1]  // 取出map 的值赋予一个变量
	fmt.Println(m_a) // OK

	// 判断一个map 有没有被初始化,使用多返回值判断
	m_b, ok := m5[2][1]
	// 判断是否被初始化操作
	if !ok {
		m5[2] = make(map[int]string)
	}
	m5[2][1] = "OK b"
	m_b,ok = m5[2][1]
	fmt.Println(m_b, ok) // OK b true

	// 迭代操作
	s_map := make([]map[int]string,5) // 以 map 为元素的slice 使用 make 创建一个切片,元素的slic
	for _,v := range s_map {
		v = make(map[int]string) // v 是值的拷贝
		v[1] = "OK"
		fmt.Println(v);
	}
	fmt.Println(s_map)

	// 针对一个 map 直接操作
	for i := range s_map {
		s_map[i] = make(map[int]string) 
		s_map[i][1] = "OK"
		fmt.Println(s_map[i]);
	}
	fmt.Println(s_map)

	// map 的间接排序
	// map 集合
	map01 := map[int]string{1:"a", 2:"b", 3:"n", 4:"c", 5:"p", 6:"f"}
	// 切片
	slice01 := make([]int, len(map01))
	i := 0
	for k, _ := range map01 {
		slice01[i] = k
		i++
	} 

	fmt.Println(slice01) // 返回的是一个无序的数组:[5 6 1 2 3 4] [3 4 5 6 1 2]
	sort.Ints(slice01)
	fmt.Println(slice01) // 有序的数组:[1 2 3 4 5 6]
}