golang基础|青训营

147 阅读7分钟

golang基础

golang特点

  • 高性能、高并发
  • 语法简单、学习曲线平缓
  • 丰富的标准库
  • 完善的工具链
  • 静态链接
  • 快速编译
  • 跨平台
  • 垃圾回收

Hello World

代码如下
在控制台中通过go run xxx.go直接运行
也可以通过go build xxx.go编译为二进制文件,然后通过./xxx运行

package main
import (
    "fmt"
)

func main() {
    fmt.Println("Hello World!")
}

变量(var)

golang变量名由字母、数字、下划线组成,其中首个字符不能为数字
golang声明变量时一般使用 var 关键字
变量声明格式:var 变量名 类型
变量批量声明:var (变量名 类型...)
变量声明并初始化格式:var 变量名 类型 = value
常用方式:变量名 :=值(通过:=声明变量可以自动根据值的内容判断类型)
注:初始化时var可以根据值来判断类型,因此使用var时类型可省略

package main
import "fmt"
var (
    name string
    age int
    sex bool
)  //变量批量声明

func main() {
    var a int //变量声明
    var b,c int = 1,2
    d :=3
}

常量(const)

常量是一个简单值的标识符,在程序运行时,不会被修改的量
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型
常量声明格式:const 变量名 类型 = value
批量声明:const 变量名1,变量名2 = value1,value2
注意:const初始化时类型同样可以省略

package main
import "fmt"

func main() {
    const a int = 1
    const b =2
    const c,d = 3,4
}

iota

iotago语言的常量计数器,只能在常量的表达式中使用
iotaconst关键字出现时将被重置为0,const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。
语言解释可能有点不明所以,看代码就知道它是什么东西了

const(
   a = iota  //值为0 ,iota为0
   b         //值为1 ,iota为1
   c         //值为2 ,iota为2
   d = "CYY" //值为CYY ,iota为3
   e         //值为CYY ,iota为4
   f = 100   //值为100 ,iota为5
   g         //值为100 ,iota为6
   h = iota  //值为7 ,iota为7
   i         //值为8 ,iota为8
)

if else

  • 可省略条件表达式括号
  • {不可独立一行,必须在条件表达式后面
  • 持初始化语句,可定义代码块局部变量
package main 
import "fmt" 

func main() { 
    // 定义一个代码块局部变量x,并进行初始化 
    if x := 10; x > 0 { 
    fmt.Println(x) // 输出:10 
    } 
    // x只在if语句块中有效,此处无法访问x 
}

for

在golang中只有for循环,没有while循环
while循环的操作可以通过for循环来实现
for循环条件表达式括号也可省略

for循环有3种方式:

 for init; condition; post { }  
 for condition { }      //while循环的实现  
 for { }      //死循环  
 //init: 一般为赋值表达式,给控制变量赋初值  
 //condition: 关系表达式或逻辑表达式,循环控制条件  
 //post: 一般为赋值表达式,给控制变量增量或减量

数组

数组定义:var 变量名 [size]int

  • 数组长度是数组类型的一部分,因此var arr1 [10] intvar arr2 [20] int的类型是不同的
  • 数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len(arr)-1
  • 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值
  • 数组长度不确定,可以使用...代替数组的长度,编译器会自动推断数组长度
  • 初始化时变量名后的类型可省略

package main
import "fmt"

func main() { 
    var arr1 [5]int = [5]int{1,2,3,4,5}
    var arr2 = [5]int{1,2,3,4,5}
    var arr3 = [...]int{1,2,3,4,5,6,7}
    
    a :=[5]int{1,2,3} //未初始化元素为0
    b :=[...]int{}
    c :=[5]int{2:1,4:2} //通过下标初始化,c[2]=1,c[4]=2
}

Slice(切片)

slice是一种可变长度的数组,也就是我们的动态数组
是数组的一个引用,因此切片是引用类型。但自身是结构体,值拷贝传递

声明一个未指定大小的数组来定义切片:var slice []int
使用make()函数创建切片:slice :=make([]type,len,capacity)
len为数组长度,可扩充
capacity为数组容量,表示数组的最大容量,是一个可选参数
len不能大于capacity

package main 
import "fmt" 

func main() {
    arr :=[5]int{1,2,3,4,5}
    var slice1 []int        //定义切片,为空切片,默认为nil,长度为0
    slice2 :=make([]int,10) //长度为10的切片,容量为len*2
    slice3 :=arr[:]         //数组转为切片
    slice4 :=arr[1,3]       //取arr[1]到arr[3]的元素创建切片
}
  • len()函数:换取切片长度
  • cap()函数:获取切片容量
  • append()函数:向切片添加元素
  • copy()函数:拷贝切片,用于扩充容量

map

定义格式:map :=make(map[keytype]valuetype,initialCapacity)
initialCapacity可省略

获取键值:value :=map[key]value,ok :=map[key]
ok值是判断键是否存在,存在ok值为true,不存在则为falsevalue值为对应类型的默认值

package main 
import "fmt" 

func main() { 
    map1 :=make(map[string]int,10)    //容量为10的空map
    map2 :=make(map[string]int){
            "num1": 1,
            "num2": 2,
            "num3": 3,
    }
    value , ok :=map2["num1"]           //获取键值
    map2["num1"] = 100                  //修改键值
    delete(map2,"num2")                 //删除键值对
}

range

golang的range类似迭代器操作,返回 (索引, 值) 或 (键, 值)

package main 
import "fmt" 

func main() { 
    map :=make(map[string]int){"num":1,}
    for key, value := range map {
        newMap[key] = value          
    }

    arr :=[]int{1,2,3,4,5}
    for _, value := range arr {      //不需要的值可以通过`_`忽略
        fmt.Println(value) 
    }
}

函数

  • 无需声明原型
  • 支持不定 变参
  • 支持多返回值
  • 支持命名返回参数。
  • 支持匿名函数和闭包
  • 函数也是一种类型,一个函数可以赋值给变量
  • 不支持 嵌套 (nested) 一个包不能有两个名字一样的函数
  • 不支持 重载 (overload)
  • 不支持 默认参数 (default parameter)

函数定义

func function_name( [parameter list] ) [return_types] {   //
   函数体
}
package main 
import "fmt" 
func add(a,b int) (sum int ,c int ,d int){
    c,d =a,b
    return a+b,c,d
}

func main() { 
    add(1,2)
}

指针

golang中的函数传参都是值拷贝
当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量
传递数据使用指针,而无须拷贝数据
类型指针不能进行偏移和运算
golang中的指针操作非常简单,只需要记住两个符号:&(取地址)和*(根据地址取值)

package main 
import "fmt" 


func main() { 
    a :=100
    b :=&a
    fmt.Printf("a:%d ptr:%p\n", a, &a) // a:100 ptr:0xc00001a078
    fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
    fmt.Println(&b)                    // 0xc00000e018
}

结构体

golang中可以使用type关键字来定义自定义类型

声明格式

type 结构体名 struct{
    结构体变量名  变量类型
    结构体变量名  变量类型
    ...
}

实例化

package main 
import "fmt" 
type student struct{
    Name string
    Age  int
    homeAddress string 
}
func main() {
    student1 :=student{Name: "CYY",Age: 20,homeAddress :"掘金总部"}
    student2 :=student{"stu",18,"掘金分部"}
    str := student1.Name
    fmt.Println(str)
}

外部包访问: 结构体大写时可被外部包访问,结构体成员变量首字母为小写时,成员变量视为私有,不可在外部包被访问,首字母为大写时可被外部包访问

Go语言开发注意事项

  1. Go源文件以go为拓展名
  2. Go应用程序的执行入口是main()函数
  3. Go语言严格区分大小写
  4. Go语言每个语句后不需要;(Go语言会在每行后自动加上)
  5. Go编译器是一行行进行编译的,因此一行只有一条语句,不能把多条语句写在同一行,否则会报错
  6. Go语言定义的变量或import的报如果未使用,代码不能编译通过
  7. 大括号是成对出现的

Go官方编程指南

API文档查询:pkg.go.dev/std

Golang 中文网 API文档:studygolang.com/pkgdoc

结言

欢迎各位大佬在评论区指出文章的错误,共同交流学习
总结的可能有点简陋,笔记部分内容参考www.topgoer.com