Go语言原理与实践总结|青训营

87 阅读8分钟

1 基础语法

1.1 代码初体验 — Hello World

package main

import(
    "fmt"
)
func main(){
    fmt.Println("hello world")
}

1.2 变量

1.2.1 变量声明

  • var 变量名 (变量类型) = 等于值

var a = "initial"

var b,c int = 1,2

  • 变量名 := 等于值

d :=100

1.2.2 常量声明

  • const 变量名 (变量类型) = 等于值

const e string = "constant"

1.3 if、for、which结构

1.3.1 if 语句

Go语言相较于C语言不同点:

  • if后面无括号

  • if后面必须接大括号

  • 格式:
if xx {
   执行1
} 

else if xy{
   执行2
} 

else {
   执行3
}

1.3.2 for循环

格式:

for initialization; condition; post{
    // 循环中执行的代码块 
}

其中,initialization 是循环变量的初始化语句,condition 是循环条件,post 是每次循环后执行的语句。这三个部分都可以省略

代码示例:

for i:=0; i<5; i++{
    //continue继续循环
    //break跳出循环
}

1.3.3 switch 语句

格式:

switch [定义变量;] [变量]{
  case [条件/具体值]:
  	//代码
  case [条件/具体值]:
  	//代码
  default:
    //代码
}

switch结构中某个最多只能执行一个case,使用fallthrough可以让下一个case/default继续执行

1.4 数组、切片

1.4.1 数组

数组是一组固定长度的数据项,它们具有相同的类型。数组的长度是在声明时指定的,不能更改。

var arr [num]type

1.4.2切片

切片是一个拥有相同类型元素的可变长度的序列。支持自动扩容。切片是一个引用类型,底层引用了一个数组,并且可以重新分配底层数组的大小。

var name []type
  • 使用make()函数构造切片
make([]T,size,cap)
//T:切片的元素类型
//size:切片中元素的数量
//cap:切片的容量
  • 基于数组定义切片

切片的底层就是一个数组,所以我们可以基于数组定义切片。

func main() {
// 基于数组定义切片
    a := [5]int{55, 56, 57, 58, 59}
    b := a[1:4]                     //基于数组a创建切片,包括元素a[1],a[2],a[3]
    fmt.Println(b)                  //[56 57 58]
    fmt.Printf("type of b:%T\n", b) //type of b:[]int
}
//还支持如下方式

//c := a[1:]    [56 57 58 59]
//d := a[:4]    [55 56 57]
//e := a[:]     [55 56 57 58 59]

切片方法

  • append():为切片添加元素
  • copy():复制切片
  • delete():

1.5 map、range

1.5.1 map

  • map定义
map[KeyType]ValueType
//KeyType:键的类型
//ValueType:键对应的值的类型

map类型的变量默认初始值为nil,需要使用 make() 函数来分配内存,语法为:

make(map[KeyType]ValueType, [cap])

其中cap为map的容量,参数不是必须得,但应该在初始化map时就为其指定一个合适的容量。

  • map的基本使用

map中的数据都是成对出现的,map的基本使用示例代码

func main(){
    m :=make(map[string]int)
    m["one"] = 1
    m["two"] = 2
    fmt.Println(m)        //map[one:1 two:2]
    fmt.Println(len(m))   // 2
    fmt.Println(m["one"]) // 1
}
  • 判断键存在

Go语言中有个判断map中键是否存在的特殊写法,格式如下:

value, ok := map[key]
  • Map的遍历

map的遍历不会按照字母顺序和插入顺序,而是随机顺序。

func main() {
	// for range遍历map
	scoreMap := make(map[string]int)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100
	scoreMap["娜扎"] = 60
        
    //遍历Key和value
    for k, v := range scoreMap {
            fmt.Println(k, v)
	}
        
    //只遍历Key
    for k:= range scoreMap{
            fmt.Println(k);
        }
}

  • 键值对删除
delete(map,key)

代码实例:

func main() {
	// 使用delete()函数删除键值对
	scoreMap := make(map[string]int)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100
	scoreMap["娜扎"] = 60
	delete(scoreMap, "小明") //将小明:100从map中删除
	delete(scoreMap, "栗子") //如果存在就删除,不存在就不操作,不报错
	for k, v := range scoreMap {
		fmt.Println(k, v)
	}
}

range

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

for key, value := range oldMap {
    newMap[key] = value
}

以上代码中的 key 和 value 是可以省略。

只想读取key,格式如下:

for key:=range oldMap
//或者
for key,_:=range oldMap

只想读value,格式如下:

for _,value :=range oldMap

1.6 函数、指针

函数

Go 语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
   函数体
}

其中:

  • func:函数由 func 开始声明
  • function_name:函数名称,参数列表和返回值类型构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。

在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是真正的返回结果,第二个值是一个错误信息

func exists(m map[string]string,k string) (v string, ok bool) {
    v,ok = m[k]
    return v, ok
}

指针

go语言中的指针支持的操作很有限,指针的一个主要用途是对于传入参数进行修改

  • 代码实例
package main

import "fmt"

func add2ptr(n *int){
    *n += 2
}

func main() {
    n:=5
    add2ptr(&n)
    fmt.Println(n)
}

1.7 结构体

结构体

结构体的格式如下:

type struct_variable_type struct{
    member definition
    ...
    member definition
}

如果要访问结构体成员,需要使用点号 . 操作符,格式为:

结构体.成员名

结构体方法

  • 定义
// 定义方法的语法格式:
func (接收者变量 接收者类型) 方法名(参数列表) (返回值列表){
    //方法体
}

// 定义结构体
type point struct {
    X int
    Y int
}

// 定义结构体方法
func (p point) print() {
    fmt.Println(p.X, p.Y)
}

1.8 错误处理

GO里预定义了一个error接口类型;错误值用来表示错误状态, 错误类型也是种数据类型,和其他数据类型一样,可以作为参数也可以作为返回值

type error interface { 
    Error() string 
}

在Go语言中,可以在函数返回值中加err,代表函数可能返回错误。

//有错误时:
return nil,err        //err可以通过errors.New()创建
//无错误时:
return n,nil

1.9 字符串

  • 字符串操作

    • strings.Contains( , ) :包含另一个字符串
    • strings.Count( , ) :返回一个字符串有几个指定的字符串
    • string.EqualFold( , ) :不区分大小写的字符串比较,区分的使用 == 就可以
    • strings.Index( , ) :寻找字符串第一次出现的位置,没有的话返回-1
    • strings.Replace(s,oldstr,newstr,n)将一个字符串中的字符串替换成另一个字符串,n表示替换几个,如果是-1表示替换所有
    • strings.Split(s,str) 将一个字符串按照指的的分隔符分割为一个字符串数组
    • strings.ToLower(s)、stings.ToUpper(s) 将字符串进行大小写的变化
  • 字符串格式化

package main

import "fmt"

type point struct{
    x, y int
}
 func main() {
     s:="hello"
     n:=123
     p:=point(1,2)
     fmt. Println(s, n) // hello 123  
     fmt. Println(p) //{12 }  

     fmt. Printf("s=%v\n", s) // s=hello  
     fmt. Printf("n=%v\n", n) // n=123  
     fmt. Printf("p=%v\n", p) // p={1 2}  
     fmt. Printf("p=%+v\n", p) // p={x:1 y:2}  
     fmt. Printf("p=%#v\n", p) // p=main. point{x:1, y:2}  
      
     f := 3.141592653  
     fmt. Println(f) // 3.141592653  
     fmt. Printf("%.2f\n", f) // 3.14  
}

1.10 JSON处理

  • 编码为JSON格式

调用Go语言内置的encoding/json标准库中的json.Marshal()函数可以对一组数据进行JSON格式的编码。

buf,err := json.Marshal(a)

如果编码成功,err将赋于零值nil,变量buf将会是一个进行JSON格式化后的[]byte类型

  • 解析JSON数据

可以使用json.Unmarshal()函数将JSON格式的文本解码为Go里面预期的数据结构。

err = json.Unmarshal(buf,&b)
  • 首字母大小写问题

Go语言中首字母编码和解析都默认是大写,若要实现json化后属性名为小写,可以使用struct tag。

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

1.11 时间处理、数字解析

时间处理

获取当前时间 time.Now()

手动构造时间-time.Date(),构造时间可以使用.来获取具体时间数值,例如:t.Year()

获取当前时间戳 t.Unix()

计算时间差 t2.Sub(t1)

格式化时间 time.Format("具体格式")

数字解析

strconv 是 Golang 中一个非常常用的包,主要用于字符串和基本数据类型之间的相互转换。

  • strconv.Atoi :Atoi 函数用于将字符串转换为 int 类型
  • strconv.Parse
    • 解析整数:strconv.ParseInt()
    • 解析布尔值:strconv.ParseBool()
    • 解析浮点数:strconv.ParseFloat()
package main

import(
    "fmt"
    "strconv"
)

func main() {
    f, _ := strconv.ParseFloat("1.234",64) 
    N, _ := strconv.ParseInt("111",10,64) 
    //  111-字符串  10-进制   64-精度
    n2, _ :=strconv.Atoi("123")
    n2,err :=strconv.Atoi("AAA")
    fmt.Println(n2,err) 
    //0 strconv.Atoi:parsing "AAA":invalid syntax

1.12 进程信息

go中通过os.Argv来得到程序执行时的指定命令行参数 os.Getenv获取环境变量,os.Setenv写入环境变量

理解与建议:go语言相较于其他语言更加简单,但如果要学好还是得要真正学习,还要不断拓展自己的知识面,要有精益求精的精神。作为一门编程语言,实践永远是必不可少的,所以学好够语言还是要做到理论与实践相结合。