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,v6 = 1,2,3
    fmt.Println(v4,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,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,golang)
}
// 定义枚举类型 2
func enums2(){
    const(
        python = 0
        // 默认和上面的值一样
        java
        golang = 1
        php
    )
    fmt.Println(python,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\n",ch)
}
package main
import "fmt"

func main(){
    var str string
    str = 'abc'
    fmt.Printf("%c\n",str[0])
    // uint8 与 byte 一样
    fmt.Printf(reflect.TypeOf(str[0]))
    // 反引号,不进行转义
    str2 := `hello
    abc \n \r ...`
    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\n",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\n",content)
    }
    
    // 选择方式二
    if content,e = ioutil.ReadFile(filename): e != nil{
        fmt.Pringln(e)
    }else{
        fmt.Printf("%s\n",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\n",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
// 也可以这样定义
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\n",p)
    fmt.Println(*p)
    // 修改数据
    *p = 20
    fmt.Println(*p,num)
    
    b := "abc"
    var ip *string = &b
    fmt.Printf("%X\n",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\n",a);
    pass_by_ref(&a);
    printf("%d\n",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,3}
    // 省略大小,编译器自动推断
    arr3 := [...]int{1,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,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,5}
    printArr(arr)
    for _,v := range arr {
        fmt.Println(v)
    }
}
package main

import "fmt"

func printArr(arr *[5]int) {
    arr[0] = 18
    for _,5}
    printArr(&arr)
    for _,v := range arr {
        fmt.Println(v)
    }
}

3. 数组切片

  • 切片操作和 python 中的 list 类似,但底层不同,go的切片是 view 操作,类似数据库的 view 操作
  • 切片结果是 slice 类型:[]类型(如:[]int),此时是对 array 的引用
  • 切片索引不能超过数组的最大索引值
func main(){
    arr := [...]int{1,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)  // 与下一行等价
    var s3 []int = make([]int,0)
    // 声明并初始化
    s4 := []int{1,4}
}

2. 内置函数

1. append()

func main(){
    var s1 []int
    s1 = append(s1,1)
    fmt.Println(s1)
    s1 = append(s1,3...)
    fmt.Println(s1)
    // 用make创建指定大小的切片
    s2 := make([]int,5)
    s2 = append(s2,6)
    fmt.Println(s2)
    // 创建并初始化
    s3 := []int{1,3}
    s3 = append(s3,5)
    fmt.Println(s3)   
}
  • 切片补充
  • 可以在切片的基础上继续切片,只要不超过原数组就行
// 切片是 view 操作
func main(){
    // 数组
    arr := [...]int{0,1,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,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:"北京",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','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,"female","beijing"}
    // 传递非指针
    temStudent(s1)
    fmt.Println("main",s1)
    // 传递非指针
    pStudent(&s1)
    fmt.Println("main",s1)
}

相关文章

类型转换 1、int转string 2、string转int 3、string转float ...
package main import s &quot;strings&quot; import...
类使用:实现一个people中有一个sayhi的方法调用功能,代码如...
html代码: beego代码:
1、读取文件信息: 2、读取文件夹下的所有文件: 3、写入文件...
配置环境:Windows7+推荐IDE:LiteIDEGO下载地址:http:...