• Go语言学习纪要-1


    Go语言学习纪要-1

    学习资料来源

    1.介绍与安装

    Golang是什么

    Go 亦称为 Golang (译注:按照 Rob Pike 说法,语言叫做 Go,Golang 只是官方网站的网址),是由谷歌开发的一个开源的编译型的静态语言

    Golang 的主要关注点是使得高可用性可扩展性Web 应用的开发变得简便容易。(译注:Go 的定位是系统编程语言,只是对 Web 开发支持较好)

    (还没有深入语言底层,粗学感觉go融合了部分C和Java的特性,相较于C它吸收了部分面向对象语言的优点,相较于Java它在底层做了面向于并发编程的优化实现,可增加了头等函数、指针等特性)

    为何选择Golang

    并发是语言的一部分

    Golang 是一种编译型语言。源代码会编译为二进制机器码。(运行速度相对较快)

    语言规范十分简洁。

    Go 编译器支持静态链接。所有 Go 代码都可以静态链接为一个大的二进制文件(译注:相对现在的磁盘空间,其实根本不大),并可以轻松部署到云服务器,而不必担心各种依赖性。

    安装

    自行搜索安装教程

    2.Hello World

    package main  //包名
    import “fmt”  //引入标准包
    func main(){  //特殊函数。程序就是从main函数开始运行,main函数必须放在main包里
     fmt.Println("Hello World")
    }
    

    3.变量

    声明语法

    var name type   //type是需要的。如果不带type,那么就需要提供初始化机制让go可以推断出类型《-也就是说Go是强类型语言
    

    e.g

    var a int
    var b,c string
    var d = 1
    var e,f = "a",1
    var (
    	g = "x"
        h = 1
    )
    i := 1
    

    4.类型

    Go支持的基本类型

    bool
    数字类型:
     int8,int16,int32,int64,int
     unit8,unit16,unit32,unit64,unit //无符号的整型
     float32,float64
     complex64,complex128 //复数类型
     byte //字节
     rune //int32的别名,代表一个代码点;代码点无论占用多少个字节,都可以用一个 rune 来表示
    string
    

    Go有非常严格的强类型转换

    Go没有自动类型提升或类型转换

    //这一点个人感觉有点不太方便

    string和int做拼接:

    var a,b = "string",1
    fmt.Println(fmt.Sprintf("%s%d",a,b))
    

    类型别名语法

    type 别名 原类型 //别名后的类型是一个新类型,与原类型不同
    

    5.常量

    定义

    在 Go 语言中,术语"常量"用于表示固定的值。

    常量的值会在编译的时候确定

    因为函数调用发生在运行时,所以不能将函数的返回值赋值给常量。

    字符串常量

    双引号中的任何值都是 Go 中的字符串常量。

    无类型的常量有一个与它们相关联的默认类型,并且当且仅当一行代码需要时才提供它

    6.函数

    定义

    函数是一块执行特定任务的代码。一个函数是在输入源基础上,通过执行一系列的算法,生成预期的输出。

    声明语法

    func 函数名(参数名 参数类型) 返回值{
    	//实现
    }
    

    支持多返回值

    e.g

    func test(a,b int,string)(int,string){
    	a++
    	return a,b
    }
    
    func test2(a int,b string)(returna int ,returnb string){
        a++
        return  //必要的
    }
    
    func main(){
        var _,b = test2(1,"3")  // _表示空白符,即不关注于值内容
        fmt.Printf(b)
    }
    

    7.包

    包用于组织 Go 源代码,提供了更好的可重用性与可读性

    main函数需要放在main包里

    //第三方包、类如何做测试呢?如何解决main包冲突问题

    //main中包名和文件路径名好像不需要一致

    属于某一个包的源文件都应该放置于一个单独命名的文件夹里。按照 Go 的惯例,应该用包名命名该文件夹。

    导入自定义包路径规则

    我们必须指定自定义包相对于工作区内 src 文件夹的相对路径

    导出名字

    在 Go 中,任何以大写字母开头的变量或者函数都是被导出的名字。其它包只能访问被导出的函数和变量。//类似于Java里的public语法

    init函数

    所有包都可以包含一个 init 函数。init 函数不应该有任何返回值类型和参数,在我们的代码中也不能显式地调用它

    包的初始化顺序如下:

    1. 首先初始化包级别(Package Level)的变量
    2. 紧接着调用 init 函数。包可以有多个 init 函数(在一个文件或分布于多个文件中),它们按照编译器解析它们的顺序进行调用。

    未使用错误屏蔽器写法

    有时候需要引入对应包,执行初始化方法,但是又不需要用到包的内容,可以用下述写法规避未使用的报错

    import (
        "geometry/rectangle"
    )
    
    var _ = rectangle.Area // 错误屏蔽器
    
    

    import (
        _ "geometry/rectangle"
    )
    func main() {
    
    }
    

    8.if-else语句

    语法

    if condition {
    } else if condition {
    } else { //注意,这里的 }要和else 在同一行,否则会被go自动补充;的规则扰乱语法
    }
    

    if statement; condition {
    }
    

    9.循环

    语法

    for initialisation; condition; post {
    }
    

    支持break和continue

    无限循环语法

    for {
    }
    

    10.switch

    语法

    支持几种语法格式

    switch [初始化语句];[判定变量]{
    case 条件值(或判定语句): //有判定变量时可以是条件值,支持多值;没有判定变量时,可以带判定语句
    	逻辑语句
        [fallthrough]  //可选的fallthrough,表示继续往下做判定检验
    ...
    default:
    	逻辑语句
    }
    

    11.数组和切片

    数组声明语法:

    var 变量名 [数组大小]数组值类型  //数组声明,用append可以进行拓展
    var 变量名 = [数组大小]数组值类型{初始化值} //声明+初始化语法
    
    e.g 
    var a [3]int
    var b = [3]int{1,2,3}
    
    

    常用数组方法

    len(数组变量) //获取数组的当前长度
    cap(数组变量) //获取数组的当前容器大小
    

    切片定义

    切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用

    切片语法

    []T //表示带有T类型的切片
    数组[startIndex:endIndex] //切片语法
    数组[:] //全切
    make(数组类型,长度,[大小]) //这种是创建一个新的切片
    变量名 := [数组大小]数字值类型{初始化值...}
    
    e.g
    b := [2]int{1,2} //注意,这里创建的是切片
    c := [3][2]string{
        {"aaa","bbb"},
        {"ccc","ddd"},
        {"eee","fff"}, //最后一个,是必要的
    }
    
    e.g
    func main{
        a := []int{1,2,3}
        b := a[1:3]
        fmt.Println("array a:",a)
        fmt.Println("array a:",b)
    }
    
    

    数组和切片的区别

    切片时指针类型,数组是值类型 //这里的意思是,用数组彼此赋值时也会是拷贝,而切片只是引用指向

    数组是静态的,不可拓展,切片可以通过append拓展 //reflect.TypeOf判定时,数组是带大小的,切片是不带大小的

    一个简单的理解可以是,数组就是cap固定且不可变的数组,而切片是cap已知但可变的数组

    切片的函数传递

    我们可以认为,切片在内部可由一个结构体类型表示。这是它的表现形式,//所以赋值时也是引用传递

    type slice struct {
        Length        int
        Capacity      int
        ZerothElement *byte
    }
    

    切片持有对底层数组的引用。只要切片在内存中,数组就不能被垃圾回收。

    一种优化方式:

    使用 copy 函数 func copy(dst,src[]T)int 来生成一个切片的副本

    12.可变参数函数

    语法

    e.g
    func append(slice []Type, eles ...Type) []Type
    
    数组或切片作为参数传递时,如果要匹配可变参数,需要加...
    e.g
    nums := []int{1,2,3}
    find(89,nums...)
    ...
    func find(a int,b ...int){
        ...
    }
    
    

    切面匹配可变参数传递时是引用传递

    e.g
    
    func main() {
    	a := []int{1,2,3}
    	change(a...)
    	fmt.Printf("after call:",a)
    }
    
    func change(a ...int){
    	a[0] = 100
    }
    
    //运行结果:after call:%!(EXTRA []int=[100 2 3])
    

    13.map

    map定义

    map 是在 Go 中将值(value)与键(key)关联的内置类型。通过相应的键可以获取到值。

    基础语法

    声明语法:
    变量名 := make(map[key类型]value类型)   //创建一个key type=string value type=int的数组
    变量名 := map[key类型]value类型{初始化值}
    
    e.g
    a := make(map[string]int)
    b := map[string]int{
        "a1":1,
        "a2":2,
    }
    
    初始化语法:
    map变量名[key值]=value值
    
    e.g
    a["key"] = 1   
    
    获取map大小
    len(map变量名)
    
    遍历语法
    for key变量名,value变量名 := range map变量{
        //逻辑代码
    }
    
    

    Map和切片一样属于引用类型

    Map的相等性

    map 之间不能使用 == 操作符判断,== 只能用来检查 map 是否为 nil

    相等判定函数范例:

    func equals(a map[string]int,b map[string]int )bool{
    	if a == nil && b == nil{
    		return true
    	}
    	if a == nil || b == nil{
    		return false
    	}
    	if len(a) != len(b){
    		return false
    	}
    	for key,_ := range a{ //这里的value需要用_,因为go会检查声明的变量有没有用到 囧~
    		if a[key] != b[key]{
    			return false
    		}
    	}
    	return true
    }
    

    14.字符串

    Go 语言中的字符串是一个字节切片

    直接以string作为参数传递时是值传递

    Go 中的字符串是兼容 Unicode 编码的,并且使用 UTF-8 进行编码

    字符串的长度

    len(字符串变量)

    字符串是不可变的

    15.指针

    什么是指针

    指针是一种存储变量内存地址(Memory Address)的变量(概念和C中的是一致的)

    基础语法

    声明语法
    *T //表示指向T类型的指针
    获取地址语法
    &a //表示获取a变量的内存地址
    解析内存地址值语法
    *a //表示获取地址a的内容
    
    e.g
    a := 1
    var b *int = &a
    var c = *b
    

    不要向函数传递数组的指针,而应该用切片

    更为简单,习惯如此

    Go不支持指针运算

    C是支持的,不支持的话会更安全

    16.结构体

    什么是结构体

    结构体是用户定义的类型,表示若干个字段(Field)的集合。(和C的结构体感觉是一样的)

    基础语法

    别名+定义
    type fruit struct{
    	name string
    	num int
    }
    a := fruit{
    	name:"apple",
    	num:1,
    }
    
    匿名定义
    a := struct{
    	name string
    	num,age int
    }{
    	name:"orange",
    	num:1,
    	age:2,
    }
    
    访问结构体的字段
    a.name
    
    匿名字段
    type Person struct{
    	string
    	int
    }
    a := Person{"R",50}
    a.string = "Z"
    
    嵌套结构体
    
    提升字段
    type Address struct{
    	string
    	int
    }
    
    type Person struct{
    	name string
    	age int
    	Address
    }
    
    a := Person{
    		name:"Z",
    		age:10,
    		Address:Address{
    			"City",
    			12,
    		},
    	}
    //提升后访问
    a.string
    
    
    

    结构体导出的字段需要用大写开头

    结构相等性

    结构体是值类型。如果它的每一个字段都是可比较的,则该结构体也是可比较的。如果两个结构体变量的对应字段相等,则这两个变量也是相等的。

  • 相关阅读:
    数据库——表操作(5)
    数据库——存储引擎(4)
    数据库——库操作(3)
    数据库——初始mysql语句(2)
    数据库——初识数据库(1)
    并发编程——协程(5)
    并发编程——IO模型(6)
    并发编程——多线程(4)
    并发编程——多进程——multiprocessing开启进程的方式及其属性(3)
    并发编程——多进程——理论(2)
  • 原文地址:https://www.cnblogs.com/ybk2018af/p/14413055.html
Copyright © 2020-2023  润新知