zoukankan      html  css  js  c++  java
  • Go基础

    0. 环境准备

    1. 安装

    • 下载并安装 goland ide 编辑器
    • 下载 golang 文件并安装

    2. 测试

    1. go

    1. 每个 go 源代码文件开头必须是,package 声明,代表数据哪个包
    2. 声明 main,代表可以编译
    3. 有且只有一个 main 函数,主函数
    4. 导入的包必须使用,不使用会报错
    5. 左括号不能单起一行,否则会报错
    • goland 会自动导入使用的包
    // test.go
    package main
    import "fmt"
    
    func main() {
        fmt.Println("hello world!")
    }
    

    2. go编译器测试

    go env
    

    3. goland编辑器

    // 命令行
    go env
    go build test.go
    ./test
    // 或者
    go run test.go
    

    web框架

    1. beego
    2. gin

    1. 基础语法

    1. 变量

    1. go关键字

    • 公共25个关键字
    break default func interface select
    case defer go map struct
    chan else goto package switch
    const fallthrough if range type
    continue for import return var

    2. 预定义的名字

    • 用于内建的常量、类型和函数

    1. 内建常量(4)

    • true、false、iota、nil

    2. 内建类型(20)

    • int、int8、int16、int32、int64(5)
    • uint、uint8、uint16、uint32、uint64 、uintptr(6)
    • float32、float64、complex64、complex128 (4)
    • bool、byte、rune、string、error(5)

    3. 内建函数(13)

    • make、len、cap、new、append、copy、close、delete
    • complex、real、imag
    • panic、recover

    3. 示例

    • 变量只要定义就必须使用,否则会报错
    package main
    import ("fmt")
    
    func main(){
        // 直接定义
        var a int
        var b int
        // 一次定义多个
        var c, d int
        // 括号里
        var(
        	e int
            f int
        )
         fmt.Println(a, b, c, d, e, f)
    }
    
    • 变量的初始化
    package main
    import ("fmt" "reflect")
    // 变量
    func main(){
        // 方式一
        var v1 int = 10
        // 方式二:编译器自动推到类型
        var v2 = 5
        fmt.Println(reflect.TypeOf(v1))
        fmt.Println(reflect.TypeOf(v2))
        // 方式三: :=  声明并赋值
        v3 := 1
        fmt.Println(reflect.TypeOf(v3))   
        // 方式四
        var v4, v5, v6
        v4, v5, v6 = 1, 2,3
        fmt.Println(v4, v5, v6)
    }
    
    • 匿名变量:解决变量定义不使用报错的问题
    package main
    import ("fmt")
    // (int, string) 定义函数的返回值,返回 2 个值
    func test()(int, string){
        return 666, 'xixi'
    }
    
    func main(){
        // 调用函数并接收返回值。定义变量接收
        // _ 表示匿名函数,防止编译不通过
        i, _ := test()
        fmt.Println(i)
    }
    

    2. 常量和枚举

    1. 常量

    1. 直接定义

    • const PI = 3.14
    package main
    import "fmt"
    // 常量
    func main(){
        const pi = 3.1415926
        fmt.Println(pi)
    }
    

    2. 通过函数

    package main
    import "fmt"
    
    const pi = 3.1415926
    func const(){
        const(
        	pi = 3.14
        )
        // 就近原则
        fmt.Println(pi)
    }
    
    func main(){
    	const()
    }
    

    3. iota常量生成器

    • 常量递增
    • 还可一参与计算
    // ista = 0 的常量
    func enums3(){
        const(
        	python = iota
            java
            golang
        )
        fmt.Printzhln(python, java, golang)
    }
    
    func enums4(){
        const(
            // 位运算,b 左移
            b = 1 << (10 * iota)
            kb
            mb
        )
        fmt.Println(b, kb, mb)
    }
    

    4. 常量补充

    • 变量、函数可以先使用后定义
    package main
    import (
    	"fmt"
    	"reflect"
    )
    
    func main(){
    	enums()
    	fmt.Println(name)
    }
    
    func enums() {
    	const(
    		a = iota
    		b
    		c = 9
    		d = iota
    		e
    		f
    	)
    	fmt.Println(a, b, c, d, e, f)
    	fmt.Println(reflect.TypeOf(f))
    }
    
    var name string = "echo"
    

    2. 枚举

    package main
    import "fmt"
    // 定义枚举类型
    func enums(){
        const(
        	python = 0
            java = 1
            golang = 2
        )
        fmt.Println(python, java, golang)
    }
    // 定义枚举类型 2
    func enums2(){
        const(
        	python = 0
            // 默认和上面的值一样
            java
            golang = 1
            php
        )
        fmt.Println(python, java, golang, php)
    }
    
    func main(){
        enums()
        enums2()
        enums3()
    }
    

    3. 基本数据类型

    1. 整型

    • int32、int64
    • uint32、uint64
    • int:一个字长
    package main
    import ("fmt", "reflect")
    // 整型
    func main(){
        // int 和 uint,一个字长
        var v1 in32
        v1 = 123
        v2 := 64
        mt.Println(reflect.TypeOf(v1))
        fmt.Println(reflect.TypeOf(v2))
    }
    

    2. 浮点型

    • float32 和 float64
    • int(a):强制类型转换s
    func main(){
        var v3 float32
        v3 = 12
        // 编译器自动推断成 一个字长
        v4 := 12.5
        mt.Println(reflect.TypeOf(v3))
        fmt.Println(reflect.TypeOf(v4))
       	
        var c float32 = 1
        fmt.Println(unsafe.Sizeof(c))
        
        // 不同类型的不能想加,编译错误
        var a = 1
        fmt.Println(a + v4)
        // 可以类型强制转换
        fmt.Println(a + int(v4))
    }
    

    3. bool

    • true 和 false
    • 注意:定义的 bool 类型不能赋值给其他类型的值
    package main
    
    func main(){
        var v1 bool
        v1 = true
        // 可以使用表达式
        v2 := (1==2)
        fmt.Println(v1, v2)
        fmt.Println(reflect.TypeOf(v2))
        // 取反
        v3 := !v2
        fmt.Println(v3)
        // 逻辑元算符
        if v3 == true && v2 == false{
            fmt.Println("right")
        }
    }
    

    4. byte 和 string

    • byte:字符,单引号
    • string:字符串,双引号
    package main
    
    // byte 类型
    func main(){
        // 字符和字符串
        var ch byte
        // 字符用单引号,字符串使用双引号
        ch = 'a'
        fmt.Println(ch)
        fmt.Printf("ch = %c
    ", ch)
    }
    
    package main
    import "fmt"
    
    func main(){
        var str string
        str = 'abc'
        fmt.Printf("%c
    ", str[0])
        // uint8 与 byte 一样
        fmt.Printf(reflect.TypeOf(str[0]))
        // 反引号,不进行转义
        str2 := `hello
        abc 
     
     ...`
        fmt.Println(str2)
    }
    

    5. 类型别名

    • go语言以包为单位
    • main.自定义类型名
    func main(){
        // 定义 myint 类型,实际就是 int
        type myint int
        var i myint = 100
        fmt.Println(i)
        // main.myint,拥有原来类型的所有性质,并且可以自定义方法
        fmt.Println(reflect.TypeOf(i))
    }
    

    6. 类型转换

    • 不支持自动类型转换
    func main(){
        var ch byte = 'a'
        // 强制转换
        var i int = int(ch)
        fmt.Println(i)
    }
    

    4. fmt 包

    • 输入、输出
    • println:默认有换行
    • print 和 printf:没有换行
    package main
    import "fmt"
    
    func main(){
        a := 15
        // 输出
        fmt.Printf("a=%d
    ", a)
        // 输入
        var v int
        fmt.Printf("请输入一个整型:")
        fmt.Scan(&v)
        fmt.Println(v)
    }
    
    • Printf():输出格式化
    格式化 功能
    %v 按值的本来值输出
    %+v 在 %v 基础上,对结构体字段名和值进行展开
    %#v 输出 Go 语言语法格式的值
    %T 输出 Go 语言语法格式的类型和值
    %% 输出 % 本体
    %b 整型以二进制方式显示
    %o 整型以八进制方式显示
    %d 整型以十进制方式显示
    %x 整型以十六进制方式显示
    %X 整型以十六进制、字母大写方式显示
    %U Unicode 字符
    %f 浮点数
    %p 指针,十六进制方式显示,并加上前导的0x

    5. 流程控制

    1. 选择

    1. if...else

    func main(){
        const filename = 'abc.txt'
        // 选择方式一
        content, e = ioutil.ReadFile(filename)
        // 相当于 None
        if e!= nil{
            fmt.Pringln(e)
        }else{
            fmt.Printf("%s
    ", content)
        }
        // 选择方式二
    	if content, e := ioutil.ReadFile(filename); e != nil{
    		fmt.Println(e)
    	}else{
    		fmt.Printf("%s
    ", content)
    	}
    }
    

    2. switch

    • 默认有 break
    package main
    import "fmt"
    
    func main(){
        res := grade(-1)
        fmt.Println(res)
    }
    
    func grade(score int)(string){
        // 定义一个 string 用于返回
        res := ""
    	switch {
    	case score < 0 || score > 100:
    		res = "输入有误"
            // 若想继续执行,添加 fallthrough
    	case score < 60:
            res = "不及格"
    	case score < 80:
            res = "良好"
    	default:
            res = "优秀"
        return res
    	}
    }
    

    2. 循环

    • for循环
    package main
    import "fmt"
    
    func main(){
    	sum(100)
    	sum2(100)
    }
    
    func sum(num int){
    	sum := 0
    	for i := 0; i <= num; i++ {
    		sum += i
    	}
    	fmt.Println(sum)
    }
    
    func sum2(num int){
    	i := 0
    	sum := 0
    	for i <= num{
    		sum += i
    		i ++
    	}
    	fmt.Println(sum)
    }
    
    • range
    func main(){
        s := 'abc'
        for i, c := range s{
            fmt.printf("%d, %c
    ", i, c)
        }
    }
    

    3. 跳转

    • break和continue
    • goto
    func main(){
        for i := 0; i<5; i++{
            fmt.println(i)
            goto OUT
        }
        
        OUT:
        fmt.println("yes")
    }
    

    2. 函数

    1. 自定义函数

    • 函数和字段,名字首字母小写代表的是private(只有包内才能调用),大写为public
    • args ...int表示任意个 int 型数据
    // 也可以这样定义
    func example(v1, v2 int){}
    
    // 不定参
    func example(args ...int){
        for _, n := range args{
            fmt.Println(n)
        }
    }
    
    // 返回多个值
    func example()(int, string){}
    // 返回一个值
    func example() int {}
    
    // 返回值,定义变量名
    func example()(a int, str string){
        a = 123
        str = 'abc'
        return
    }
    
    • 1-100的和
    package main
    
    import "fmt"
    
    func main() {
    	res := rsum(100)
    	fmt.Println(res)
    
    }
    
    // 循环版
    func sum(num int) (res int) {
    	res = 0
    	for i := 1; i <= num; i++ {
    		res += i
    	}
    	return
    }
    
    // 递归版
    func rsum(num int) (res int) {
    	if num == 1 {
    		return 1
    	}
    	return num + rsum(num-1)
    }
    

    2. defer 关键字

    1. 功能

    1. defer⽤于延迟一个函数或者方法的执行
    2. defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁
    3. 通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放
    4. 释放资源的defer应该直接跟在请求资源的语句后,以免忘记释放资源

    2. 单个defer

    func main(){
        // 延迟执行,一般用于资源关闭
        defer fmt.Println("defer")
        fmt.Println("main")
    }
    

    2. 多个defer

    • 逆序执行,即使有异常也会继续执行
    func main(){
        defer fmt.Println("a")
        defer fmt.Println("b")
        defer test(0)
        defer fmt.Println("c")
    }
    // c b a
    
    func test(num int){
        fmt.Println(100/num)
    }
    

    3. 复合数据类型

    • 总共 5 种数据类型
    类型 名称 默认值
    pointer 指针 nil
    array 数组 0
    slice 切片 nil
    map 字典 nil
    struct 结构体 -

    1. 指针

    1. &a:代表取a的地址
    2. 指针和变量是配合使用的
    3. 指针也有类型,只能指向定义类型的数据,如果是对象定义类名

    1. 定义和初始化

    func main(){
        a := 10
        var p *int = &a
        fmt.Printf("%x
    ", p)
        fmt.Println(*p)
        // 修改数据
        *p = 20
        fmt.Println(*p, num)
        
    	b := "abc"
    	var ip *string = &b
    	fmt.Printf("%X
    ", ip)
    	fmt.Println(*ip)
    }
    

    2. 空指针

    • var ptr *int
    // 是否为空的判断
    if ptr == nil{
        fmt.Println("ptr指针为空")
    }
    

    3. 值传递和引用传递

    • 值传递:相当于是变量的副本,不会修改原来的变量
    • 引用传递:传递的是变量的地址,相当于是指针
    • go语言,函数传参都是值传递,会单独开启一块内存空间
    // c 语言版本
    void pass_by_val(int a){
        a++;
    }
    void pass_by_ref(int *a){
        (*a)++;
    }
    
    int main(){
        int a = 3;
        pass_by_val(a);
        printf("%d
    ", a);
        pass_by_ref(&a);
        printf("%d
    ", a);
    }
    
    // go 语言版本的交换数据
    func swap(a, b *int){
        *a, *b = *b, *a
    }
    
    func main(){
        a, b := 3, 4
        swap(&a, &b)
        fmt.Println(a, b)
    }
    

    2. new() 和 make()

    1. new()用来分配内存,但与其他语言中的同名函数不同,它不会初始化内存只会将内存置零
    2. make(t Type, size ... IntergerType)会返回一个指针,该指针指向新分配的,类型为 t 的零置,适用于创建结构体
    3. make()的目的不同于new(),它只能创建 slice、map、channel,并返回类型为T(非指针)的已初始化(非零值)的值
    4. new是一般是创建对象的,也可以创建变量。
    func main(){
        // new
        p := new([] int)
        fmt.Println(p)
        // make,   类型, 长度,容量
        v := make([] int, 10, 50)
        fmt.Println(v)
    }
    

    2. 数组

    1. 声明数组

    1. 一维数组

    // 数据定义
    func main(){
       	// 直接定义
    	var arr1 [10] int  
        // :=
        arr2 := [3]int{1,2,3}
        // 省略大小,编译器自动推断
        arr3 := [...]int{1,2,3,4,5}
        fmt.Println(arr1, arr2, arr3)
    }
    

    2. 二维数组

    • 定义
    func main(){
        var grid [4][5] int
        fmt.Println(grid)
    }
    

    2. 数组遍历

    // 数据定义
    func main(){
        arr := [...]int(1,2,3,4,5)
        // 方式一
        for i:=0; i<len(arr3); i++{
            fmt.Println(arr[i])
        }
        // 方式二
        for _, v := range arr{
            fmt.Println(v)
        }
    }
    
    • 数组传递是传值还是引用?
    // 数组的传递是值传递
    package main
    import "fmt"
    
    func printArr(arr [5]int) {
    	arr[0] = 18
    	for _, v := range arr {
    		fmt.Println(v)
    	}
    }
    
    func main() {
    	arr := [...] int{1, 2, 3, 4, 5}
    	printArr(arr)
    	for _, v := range arr {
    		fmt.Println(v)
    	}
    }
    
    package main
    
    import "fmt"
    
    func printArr(arr *[5]int) {
    	arr[0] = 18
    	for _, v := range arr {
    		fmt.Println(v)
    	}
    }
    
    func main() {
    	arr := [...] int{1, 2, 3, 4, 5}
    	printArr(&arr)
    	for _, v := range arr {
    		fmt.Println(v)
    	}
    }
    

    3. 数组切片

    • 切片操作和 python 中的 list 类似,但底层不同,go的切片是 view 操作,类似数据库的 view 操作
    • 切片结果是 slice 类型:[]类型(如:[]int),此时是对 array 的引用
    • 切片索引不能超过数组的最大索引值
    func main(){
        arr := [...]int{1,2,3,4,5,6,7,8,9}
        fmt.Println(arr[2:6])
    }
    

    3. slice

    1. 定义

    1. 数组的长度固定,go 提供了数组切片(slice)
    2. 取值时,索引值超出范围会报错
    func main(){
        // 声明切片,只是比数组少了长度
        var s1 [] int
        // :=
        s2 := []int{}
        // make()
        var s3 []int = make([]int, 0, 0)  // 与下一行等价
        var s3 []int = make([]int, 0)
        // 声明并初始化
        s4 := []int{1,2,3,4}
    }
    

    2. 内置函数

    1. append()

    func main(){
    	var s1 []int
        s1 = append(s1, 1)
        fmt.Println(s1)
        s1 = append(s1, 2, 3...)
        fmt.Println(s1)
       	// 用make创建指定大小的切片
        s2 := make([]int, 5)
        s2 = append(s2, 6)
        fmt.Println(s2)
        // 创建并初始化
        s3 := []int{1,2,3}
        s3 = append(s3, 4,5)
        fmt.Println(s3)   
    }
    
    • 切片补充
    • 可以在切片的基础上继续切片,只要不超过原数组就行
    // 切片是 view 操作
    func main(){
        // 数组
        arr := [...]int{0, 1,2,3,4,5,6,7}
        s1 := arr[2:4]
    	fmt.Println(s1, s1[0], s1[1], s1[:6])
        fmt.Println(len(s1))
        fmt.Println(cap(s1))			// 容量到原数组结尾
    }
    

    2. copy()

    • 两个切片之间复制数据
    func main(){
        arr := [...]int{0,1,2,3,4,5,6,7,8,9}
        s1 := arr[8:]  // 8,9
        s2 := arr[:5]	// 0,1,2,3,4
        // 将第二个切片元素copy到第一个
        // si从头开始覆盖,索引对应位置赋值,不同位置不变
        copy(s2, s1)
    }
    

    4. Map

    1. 定义

    • 类似python的dict
    • 无序的健值对的集合,可以通过key找到value值
    func main(){
        // 定义map,直接声明
        var m1 map[int] string
        var m11 map[int] string = map[int]string{1:"abc", 2:"def"}
        // :=
        m2 := map[int]string{}
        m2 := map[int]string{1:"abc", 2:"def"}
        // make()
        m3 := make(map[int]string)
        // 指定容量的 make()
        m4 := make(map[int]string, 10)
        fmt.Println(m1, m2, m3)
    	fmt.Println(m4, len(m4),)
    }
    

    2. 键值操作

    func main(){
        m1 := map[int]string{1:"北京", 2:"上海", 3:"广州"}
        // 增加
        m1[4] = "杭州"
        // 修改
        m1[1] = "beijing"
        fmt.Println(m1)
        // 删除
        delete(m1, 2)
        fmt.Println(m1)
    }
    

    3. 遍历

    func main(){
        m1 := map[int]string{1:"北京", 2:"上海", 3:"广州"}
        // 遍历
        for k, v := range m1{
            fmt.Println(k, v)
        }
        // 判断某个key对象的value是否存在
        val, ok := m1[1]
        fmt.Println(val, ok)
    }
    

    5. 结构体

    1. 定义和初始化

    • go语言没有class,只有结构题 struct
    // 定义 type 结构体名 struct{}
    // 学生的结构体
    type Student struct{
        id int
        name string
        gender byte
        age int
        address string
    }
    
    func main(){
        // 顺序初始化
        var s1 Student = Student{1, "john", 'f', 20, "beijing"}
        // 指定初始化
        s2 := Student{id:2, age:20}
        // 结构体作为指针变量初始化
        var s3 *Student = &Student{3, "tom", 'm', 20, 'bj'}
        fmt.Println(s1, s2, s3)
        fmt.Println(s1.id, s1.name)
        // 获取指针对象的字段
        fmt.Println((*s3).name)
        fmt.Println(s3.name)      // 底层会转为 (*s3).name
        
    }
    

    2. 结构体参数

    • 结构体可以作为函数参数传递
    // 定义 type 结构体名 struct{}
    // 学生的结构体
    type Student struct{
        id int
        name string
        gender string
        age int
        address string
    }
    // 定义传递学生对象的方法
    func temStudent(tmp Student){
        tmp.id = 250
        fmt.Println("temStudent", tmp)
    }
    
    // 传递指针对象
    func pStudent(p *Student){
        p.id = 300
        fmt.Println("pStudent", p)
    }
    
    func main(){
        // 顺序初始化
        var s1 Student = Student{1, "john", "female",  20, "beijing"}
        // 传递非指针
        temStudent(s1)
        fmt.Println("main", s1)
        // 传递非指针
        pStudent(&s1)
        fmt.Println("main", s1)
    }
    

    4. 面向"对象"

    1. 实现类的特性

    1. 没有封装、集成和多态的概念,同样通过结构体实现这些特性
    type Person struct{
        name string
        age int
        gender string
    }
    
    type Student struct{
        Person					// 匿名字段
        id int
        addr string
        name string
    }
    
    func main(){
        s1 := {Person{"echo", "21", "female"}, id :1, name:"henry"}
        var s Student
        s.name = "henry"
        fmt.Println(s)
        s.Person.name = "dean"
        fmt.Println(s)
    }
    
    • 同名字段情况:赋值问题
    • 所有的内置类型和自定义类型都可以作为匿名字段去使用
    • 指针类型匿名字段
    type Person struct{
        name string
        age int
        gender string
    }
    
    type Student struct{
    	*Person					// 匿名字段
        id int
    }
    
    func main(){
        s1 := {&Person{"echo", "21", "female"}, id :1, name:"henry"}
        var s Student
        s.name = "henry"
        fmt.Println(s)
        s.Person.name = "dean"
        fmt.Println(s)
    }
    

    2. 方法

    1. 定义

    • func (接收参数 接收类型) 方法名 (参数列表) (返回值)
    type Myint int
    // 面向过程
    func Add(a, b Myint) Myint{
        return a + b
    }
    // 面向对象
    func (a Myint) Add(b, Myint) Myint{
        return a + b
    }  
    
    func main(){
        var a Myint = 1
        var b Myint = 1
        fmt.Println(Add(a, b))
        fmt.Println(a.Add(b))   
    }
    
    type Person struct{
        name string
        gender string
        age int
    }
    
    func (p Person)PrintInfo(){
        fmt.Println(p.name, p.gender, p.age)
    }
    
    func main(){
        p := Person{"echo", "female", 18}
        p.PrintInfo()
    }
    

    2. 值语义和引用语义

    1. 值语义:不会改变原有数据的值
    2. 引用语义:可以修改原来数据
    type Person struct{
        name string
        gender string
        age int
    }
    
    // 引用语义
    func (p *Person)SetInfoPointer(){
        (*p).name = "dean"
        p.gender = 22
    }
    
    // 值语义
    func (p Person)SetInfoValue(){
        p.name = "eliane"
        p.gender = "female"
        p.age = 23
    }
    
    func main(){
        p := Person{"test", "male", 10}
        (&p).SetInfoPointer()
        fmt.Println(p)
        // 值语义,并不会改变原来的值
        p2 := Person{"exam", "female", 100}
        p2.SetInfoValue()
        fmt.Println(p)
    }
    

    3. 方法的继承

    type Person struct{
        name string
        gender string
        age int
    }
    
    func (p *Person)SetInfoPointer(){
        (*p).name = "dean"
        p.gender = 22
    }
    
    type Student struct{
        Person
    }
    
    func main(){
        s := Student{Person{"henry", "male", 18}}
        s.SetInfoPointer()
    }
    

    4. 方法的重写

    type Person struct{
        name string
        gender string
        age int
    }
    
    func (p Person)PrintInfo(){
        fmt.Println("Person", p.name, p.gender, p.age)
    }
    
    type Student struct{
        Person
        id int
        addr string
    }
    // 方法重写
    func (s Student)PrintInfo(){
        fmt.Println(s.name, s.gender, s.age)
    }
    
    func main(){
        p := Person{"henry", "male", 18}
        p.PrintInfo()
        s := Student{Person{"echo", "female", 16}, 2, "bj"}
        s.PrintInfo()
        // 去调用 person 的方法
        s.Person.PrintInfo()
    }
    

    5. 方法值和方法表达式

    package main
    import "fmt"
    type Person struct {
    	name string
    	age  int
    }
    
    func (p *Person) SetInfo() {
    	(*p).name = "henry"
    	p.age = 19
    }
    
    func main() {
    	p := Person{"echo", 18}
    	v := p.SetInfo								// 方法值
    	v()
    	fmt.Println(p)
    	f := (*Person).SetInfo						// 方法表达式
    	f(&p)
    	fmt.Println(p)
    }
    
    • 创建属性getter和setter 方法并调用
    type Dog struct{
        name string
        gender int
    }
    
    func (d *Dog)SetName(name string){
        d.name = name
    }
    
    func (d *Dog)GetName()string{
        return d.name
    }
    
    func (d *Dog)bite(){
        fmt.Println("dog", d.name)
    }
    
    func test01(){
        d := Dog{"erha", 1}
        d.bite()
    }
    
    func main(){
        test01()
    }
    

    3. 包和封装

    1. 包的调用

    • 包名.公共方法
    
    

    2. 接口

    1. 接口(interface)是一个自定义类型,描述了一系列方法集合
    2. 接口不能被实例化
    3. 接口名习惯以 er 结尾**

    1. 接口使用

    // 接口
    type Humaner interface{
        // 方法
        Speak()
    }
    // 结合多态
    type Student struct{
        name string
        score int
    }
    type Teacher struct{
        name string
        group string
    }
    // 自定义类型
    type MyStr string
    
    // 实现接口的方法
    func (*s Student)Speak(){
        fmt.Printf("student[%s, %d]
    ", s.name, s.score)
    }
    func (*t Teacher)Speak(){
        fmt.Printf("teacher[%s, %d]
    ", t.name, t.group)
    }
    func (str MyStr)Speak(){
        fmt.Printf("MyStr[%s]
    ", "working")
    }
    // 多态的核心,参数为接口类型
    func Who(i Humaner){
        i.Speak()
    }
    
    func main(){
        s := &Student{"henry", 90}
        t := &Teacher{"dean", "golang"}
        var tmp MyStr = "abc"
        // 基本调用
        s.Speak()
        t.Speak()
        tmp.Speak()
        // 多态
        Who(s)
        Who(t)
        Who(tmp)
    }
    

    2. 接口继承

    • 和类的继承一样
    type SuperHumaner interface {
        Humaner
    }
    func SuperWho(i SuperHumaner){
        i.Speak()
    }
    
    func main(){
        s := Student{"henry", 19}
        SuperWho(s)
    }
    

    3. 空接口

    • 代表是任意类型,如fmt.Printf()
    • ...interface{}:表示任意格式的接口
    func Println(a ...interface{}) (n int, err error) {
    	return Fprintln(os.Stdout, a...)
    }
    

    4. 类型查询

    • comma-ok:断言
    • value.(type):获取变量类型
    • val, ok := value.(int):判断 val 是否是 int 类型数据
    // 空接口
    type Element interface{}
    type Person struct{
        name string
        age int
    }
    
    func main(){
        list := make([]Element, 3)
        list[0] = 1
        list[1] = "hello"
        list[2] = Person{"echo", 18}
        for index, element := list{
            // 类型断言:val, ok = element.(T)
            if , ok = element.(int); ok{
                fmt.Printf("list[%d]是int类型,值是%d
    ", index, val)
            }else if val, ok = element.(string); ok{
                fmt.Printf("list[%d]是string类型,值是%s
    ", index, val)
            }else{
                fmt.Println("list[%d]是其他类型")
            } 
        }   
    }
    
    • switch测试
    for index, element := list{
        // 类型断言:val, ok = element.(T)
        switch value.(type){
            case int:
            fmt.Printf("%d是int型,值为%d
    ", index, value)
            case string:
            fmt.Printf("%d是string型,值为%s
    ", index, value)
            default:
            fmt.Printf("%d是其他类型", index)
        }   
    

    5. 异常处理

    1. 系统抛

    func test(){
        a := [5]int{1,2,3,4,5}
        index := 10
        a[index] = 123
    }
    
    func main(){
        test()
    }
    

    2. 自己抛

    package main
    import "fmt"
    
    func main(){
    	fmt.Println(Improve(8))
        fmt.Println(Improve(-8))
    }
    
    func GetCircleArea(radius float64) (area float64){
    	if radius < 0{
    		panic("半径不能 < 0")
    	}
    	area = 3.14 * radius * radius
    	return
    }
    
    func Improve(radius float64) (area float64){
    	defer func(){
    		if err := recover(); err != nil{
    			fmt.Println(err)
    		}
    	}()
    	area = GetCircleArea(radius)
    	return
    }
    

    3. 处理异常

    • bytes, e := ioutil.ReadFile()
    • 定义函数时,一般需要处理异常
    func getCircleArea(radius float32)(area float32, err error){
        if radius < 0{
            // 创建异常并返回
            err = errors.New("半径不能为负")
            return
        }
        ret = 3.14 * radius * radius
        return
    }
    
    func main(){
        ret, err := getCircleArea(-5)
        if err != nil{
            fmt.Println(err)
        }else{
            fmt.Println(ret)
        }
    }
    

    6. 字符串和时间日期类型

    1. 字符串

    1. 字符串原理

    1. 字符串底层就是bytes数组
    2. 字符串是由 byte 字节组成,字符串船渡就是byte字节长度
    3. 字符串中的字符串是不能直接修改的
    4. rune 类型用于表示utf8的类型

    1. 修改字符

    // 修改字符串中的内容
    var str = "hello"
    bs := []byte(str)
    bs[0] = "a"
    // 切片需要转回string
    str = string(bs)
    fmt.Println(str)
    

    2. rune 类型

    • 一个rune字符由 1 个或多个 byte 类型组成
    str := "hello"
    fmt.Println(len(str))
    // 每个中文占 3个字节
    str2 := "hello您好"
    fmt.Println(len(str2))
    // 将string 转为 rune
    r := []rune(str)
    fmt.Println(len(r))
    

    3. 字符串反转

    package main
    import "fmt"
    
    func main() {
    	var str string = "hello您好"
    	rs := strReverse(str)
    	fmt.Println(rs)
    	if str == rs{
    		fmt.Println("是回文")
    	}else{
    		fmt.Println("不是回文")
    	}
    }
    
    func strReverse(str string) string{
    	// 字符串的反转
    	r := []rune(str)
    	for i := 0; i < len(r)/ 2; i++ {
    		r[i], r[len(r)-1-i] = r[len(r)-1-i], r[i]
    	}
    	return string(r)
    }
    

    2. 字符串操作

    • 可以通过Go标准库中的stringsstrconv两个包中的函数进行相应的操作

    1. func len(v Type) int

    • 获取字符串长度
    func main(){
        fmt.Println(len("hello"))
    }
    

    2. func Contains(s, substr string) bool

    • n 字符串s中是否包含substr,返回bool值
    func main(){
    	fmt.Println(strings.Contains("hello", "h"))
    }
    

    3. func HasPrefix(s, prefix string) bool

    • 判断字符串s是否以prefix为开头
    • HasSuffix是判断结尾
    func main(){
    	fmt.Println(strings.HasPrefix("hello", "h"))
        fmt.Println(strings.HasSuffix("hello", "h"))
    }
    

    4. func Join(a []string, sep string) string

    • 字符串链接,把slice a通过sep链接起来
    func main(){
    	sli := []string{"w", "o", "r", "l", "d"}
    	fmt.Println(strings.Join(sli, "*"))
    }
    

    5. func Index(s, sep string) int

    • 字符串s中查找sep所在的位置,返回位置值,找不到返回-1
    • LastIndex是从后往前查找
    func main(){
    	fmt.Println(strings.Index("hello", "o"))
    }
    

    6. func Repeat(s string, count int) string

    • 重复s字符串count次,最后返回重复的字符串
    func main(){
    	fmt.Println(strings.Repeat("hello", 3))
    }
    

    7. func Replace(s, old, new string, n int) string

    • 在s字符串中,把old字符串替换为new字符串n表示替换的次数,小于0表示全部替换
    func main(){
    	fmt.Println(strings.Replace("hello", "l", "world", 1))
    }
    

    8. func Split(s, sep string) []string

    • 把s字符串按照sep分割,返回slice
    • sep不会保留
    func main(){
    	fmt.Println(strings.Split("hello", "l"))
    }
    

    9. func Trim(s string, cutset string) string

    • 在s字符串的头部和尾部去除cutset指定的字符串
    func main(){
    	fmt.Println(strings.Trim("hello", "ho"))
    }
    

    10. func Fields(s string) []string

    • 去除s字符串的空格符,并且按照空格分割返回slice
    func main(){
    	fmt.Println(strings.Fields("    hel lo "))
    }
    

    3. 字符串转换

    • Append系列函数:将整数等转换为字符串后,添加到现有的字节数组中
    func main(){
        str := make([]byte, 0, 100)
    	str = strconv.AppendInt(str, 4567, 10)
    	str = strconv.AppendBool(str, false)
    	str = strconv.AppendQuote(str, "abcdefg")
    	str = strconv.AppendQuoteRune(str, '单')
    	fmt.Println(string(str))
    }
    
    • Format系列函数:把其他类型的转换为字符串
    func main(){
    	a := strconv.FormatBool(false)
    	b := strconv.FormatInt(-1234, 10)
    	//Uint无符号
    	c := strconv.FormatUint(1234, 10)
    	//与FormatInt一样,简写
    	d := strconv.Itoa(-2234)
    	fmt.Println(a, b, c, d)
    	fmt.Println(reflect.TypeOf(a))
    }
    

    2. 时间和日期

    1. time包下的 Time 类型用来表示时间
    2. time.Now():获取当前时间
    3. time.Now().Unix():获取时间戳

    1. 简单使用

    now := time.Now()
    // 分别获取年月日
    year := now.Year()
    month := now.Month()
    day := now.Day()
    hour := now.Hour()
    minute := now.Minute()
    second := now.Second()
    fmt.Printf("%02d-%02d-%02d %02d:%02d:%02d
    ", year, month, day, hour, minute, second)
    // 获取时间戳
    timestamp := time.Now().Unix()
    

    2. 时间戳转时间

    // 获取时间戳对象
    timeObj = time.Unix(timestamp, 0)
    year := timeObj.Year
    ...
    

    3. time.Now().Format()

    • 时间格式化
    now := time.Now()
    fmt.Println(now)
    // golang 中指定为语言诞生时间,时间格式化
    timeStr := now.Format("2006/01/02 15:04:05")
    fmt.Printf("time:%s
    ", timeStr)
    
  • 相关阅读:
    10分钟学会React Context API
    Soft skill
    前端-页面性能调试:Hiper
    js对secure的支持是没问题的,httponly是为限制js而产生的,当然httponly的cookie也不会被js创建
    关于go的不爽
    Windows上mxnet实战深度学习:Neural Net
    wget获取https资源
    使用windows上 mxnet 预编译版本
    NVIDA 提到的 深度框架库
    Windows下编译mxnet
  • 原文地址:https://www.cnblogs.com/henryw/p/11587654.html
Copyright © 2011-2022 走看看