• Go基础


    Go语言

    Go 语言最主要的特性:

    • 自动垃圾回收

    • 更丰富的内置类型

    • 函数多返回值

    • 错误处理

    • 匿名函数和闭包

    • 类型和接口

    • 并发编程

      goroute,轻量级线程,创建成千上万个goroute成为可能

      基于CSP(Communicating Sequential Process)模型实现

      func main(){
          go fmt.Println("Hello world!")
      }
      
    • 反射

    • 语言交互性

    • channel

      • 管道,类似unix/linux中的pipe

      • 多个goroutine之间通过channel进行通信

      • 支持任何类型

        package main
        
        func main(){
        	pipe := make(chan int , 3)
        	pipe <- 1
        	pipe <- 2
        	pipe <- 3
        }
        
        
        
        //取数据
        
        

    结构

    • 包声明
    • 引入包
    • 函数
    • 变量
    • 语句 & 表达式
    • 注释

    Hello world

    package main
    import "fmt"
    
    func main(){
        /* 这是第一个程序 */
        fmt.Println("Hello world!")
    }
    
    1. 第一行代码package main定义了包名,package main表示一个可独立执行的程序,每个go应用程序包含一个名为main的包.
    2. 第二行import "fmt" 告诉 Go编译器,这个程序需要使用fmt包的函数,或其他元素,fmt包实现了格式化IO(输入/输出)的函数.
    3. 第三行func main()是程序开始执行的函数,main函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有int()函数则会先执行该函数).
    4. 第四行/*...*/是注释,在程序执行时将被忽略.单行注释是最常见的注释形式,多行注释也叫块注释
    5. 第五行fmt.Println(...)可以将字符串输入到控制台.
    6. 当标识符(包括常量,变量,类型,函数名,结构字段等等)以一个大写字母开头.使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的public);标识符如果以小写字母开头,则对包外是可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的protected).

    Go标记

    fmt.Println("Hello world!")
    

    行分隔符

    在Go程序中,一行代表一个语句结束.

    注释

    // 单行注释
    
    /*
    多行注释,或称块注释
    */
    

    标识符

    标识符用来命名变量,类型等程序实体,一个标识符实际上就是一个或是多个字母(A~Za~z)数字(0~9),下划线~组成的序列,但是第一个字符必须是字母下划线而不是数字

    关键字

    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
    36个预定义标识符
    append bool byte cap close complex complex64 complex128 uint16
    copy false float32 float64 imag int int8 int16 uint32
    int32 int64 iota len make new nil panic uint64
    print println real recover string true uint uint8 uintptr

    程序一般由关键字,常量,变量,运算符,类型和函数组成

    程序中可能会使用到这些分隔符:括号(),中括号[ ]和大括号{ }

    程序中可能会使用到这些标点符号:. , ;...

    Go语言的空格

    Go语言中变量的声明必须使用空格隔开

    var age int;
    

    Go语言数据类型

    在Go编程语言中,数据类型用于声明函数和变量

    数据类型的出现是味蕾把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,可充分使用内存

    类型 描述
    布尔型 布尔型的指只可以是常量true和false
    数字类型 整型int和浮点型float32,float64,Go语言支持整型和浮点型数字,并且原声支持复数,其中位的运算采用补码
    字符串类型 字符串就是一串固定长度的字符连接起来的字符序列,Go的字符串是有单个字节连接起来.Go语言的字符串的字节使用UTF-8编码标识Unicode文本
    派生类型 *指针类型(Pointer) *数组类型 *结构化类型(struct) *Channel类型 *函数类型 *切片类型 *接口类型(interface) *Map类型

    数字类型

    类型 描述
    uint8 无符号8位整数(0到255)
    uint16 无符号16位整数(0到65535)
    uint32 无符号 32 位整型 (0 到 4294967295)
    uint64 无符号 64 位整型 (0 到 18446744073709551615)
    int8 有符号 8 位整型 (-128 到 127)
    int16 有符号 16 位整型 (-32768 到 32767)
    int32 有符号 32 位整型 (-2147483648 到 2147483647)
    int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)
    浮点型
    类型 描述
    float32 IEEE-754 32位浮点型数
    float64 IEEE-754 64位浮点型数
    complex64 32位实数和虚数
    complex128 64位实数和虚数
    其他数字类型
    类型 描述
    byte 类似uint8
    rune 类似int32
    uint 32或64位
    int 与uint一样大小
    uintptr 无符号整型,用于存放一个指针


    Go语言变量

    变量来源数学,是计算机语言中能存储计算结果或能表示值抽象概念,变量可以通过变量名访问

    Go语言变量名由字母,数字,下划线组成,其中首个字母不能为数字

    • 声明变量一般形式是使用var关键字
    var identifier type
    
    变量声明
    • 指定变量类型,声明后若不赋值,使用默认值
    var v_name v_type
    v_name = vlaue
    
    • 根据值自行判定变量类型
    var v_name = value
    
    • 省略var 注意: =左侧的变量不应该是已经声明过的,否则导致编译错误
    v_name := value
    
    var a int = 10
    var b = 10
    c := 10
    
    多变量声明
    package main
    
    var x,y int
    var(
    	a int
    	b bool
    )
    
    var c, d int = 1, 2
    
    var e, f = 123, "hello"
    
    //这种不带声明格式的只能在函数体中出现
    //g,h := 123, "hello"
    
    func main(){
    	g,h := 123, "hello"
    	println(x,y,a,b,c,e,f,g,h)
    }
    
    输出结果
    0 0 0 false 1 123 hello 123 hello
    
    

    在相同的代码块中,不可以再次对于相同名称的变量使用初始化声明

    package main
    
    import "fmt"
    var a string = "abc"
    func main(){
    	fmt.Print("hello world!",a,"
    ")
    	a = "bdc"
    	fmt.Print("hello world!",a,"
    ")
    	b := "Hello world!"
    	fmt.Print(b)
    }
    
    输出结果
    hello world!abc
    hello world!bdc
    Hello world!
    


    Go语言常量

    常量是一个简单的标识符,在程序运行时,不会被修改的量

    常量中的数据类型只可以是布尔型, 数字型(整数型,浮点型和复数) 和 字符串型

    const identifier [type] = value
    
    常量类型
    • 显式类型定义: const b string = "abc"
    • 隐式类型定义: const b = "abc"
    多个相同类型的声明
    const c_name1, c_name2, c_name3 = value1, value2, value3
    
    package main
    import "fmt"
    func main(){
    	const LENGTH int = 10
    	const WIDTH int = 5
    	var area int
    	const a, b, c = 1, false, "str" // 多重赋值
    
    	area = LENGTH * WIDTH
    	fmt.Printf("面积为: %d",area)
    	println()
    	println(a,b,c)
    }
    
    输出结果
    面积为: 50
    1 false str
    
    常量用作枚举
    package main
    
    import "unsafe"
    
    const(
    	a = "abc"
    	b = len(a)
    	c = unsafe.Sizeof(a)
    )
    
    func main(){
    	println(a,b,c)
    }
    
    输出结果
    abc 3 16
    
    

    iota

    iota 特殊常量 可以认为是一个可以被编译器修改的常量

    在每一个const关键字出现时, 被重置为0, 然后在下一个const出现之前, 每出现一次iota, 其所代表的数字会自动增加1

    iota 用作 枚举值
    package main
    import "fmt"
    func main(){
    	const(
    		a = iota
    		b = iota
    		c = iota
    	)
    	fmt.Printf("a = %d, b = %d, c = %d ",a,b,c)
    	const(
    		e = iota
    		f
    		g
    	)
    	fmt.Printf("e = %d, f = %d, g = %d ",e,f,g)
    }
    
    输出结果
    a = 0, b = 1, c = 2 e = 0, f = 1, g = 2
    


    package main
    
    import "fmt"
    
    func main(){
    	const(
    		a = iota	//0
    		b			//1
    		c = 3		//3
    		d = "ha"	//独立值, iota += 1
    		e			// "ha", iota += 1
    		f = 100		// iota += 1
    		g			//100 iota += 1
    		h = iota	//7 恢复计数
    		i			//8
    	)
    	fmt.Printf("a = %d, b = %d, c = %d , d = %s, e = %s, f = %d, g = %d, h = %d, i = %d",a,b,c,d,e,f,g,h,i)
    }
    
    输出结果
    a = 0, b = 1, c = 3 , d = ha, e = ha, f = 100, g = 100, h = 7, i = 8
    


    package main
    
    import "fmt"
    
    const (
    	i = 1 << iota  // i = 1:左移0位,不变仍为1
    	j = 3 << iota  // j = 3:左移1位,变为二进制110, 即6
    	k			   // k = 3:左移2位,变为二进制1100, 即12
    	l			   // l = 3:左移3位,变为二进制11000, 即24
    )
    func main(){
    	fmt.Println("i = ",i)
    	fmt.Println("j = ",j)
    	fmt.Println("k = ",k)
    	fmt.Print("l = ",l)
    }
    
    输出结果
    i =  1
    j =  6
    k =  12
    l = 24
    


    Go语言运算符

    Go语言内置的运算符
    • 算术运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
    • 赋值运算符
    • 其他运算符
    算术运算符
    运算符 描述
    + 相加
    - 相减
    * 相乘
    / 相除
    % 求余
    ++ 自增
    -- 自减
    关系运算符
    运算符 描述
    == 检查两个值是否相等
    != 检查两个值是否不相等
    > 检查左边值是否大于右边值
    < 检查右边值是否大于左边值
    >= 检查左边值是否大于等于右边值
    <= 检查右边值是否大于等于左边值
    逻辑运算符
    运算符 描述
    && 逻辑AND运算符
    || 逻辑OR运算符
    | 逻辑NOT运算符
    位运算符
    p q p&q p|q p^q
    0 0 0 0 0
    0 1 0 1 1
    1 1 1 1 0
    1 0 0 1 1
    运算符 描述
    & 按位与运算符&是双目运算符
    | 按位或运算符|是双目运算符
    ^ 按位异或运算符^是双目运算符
    << 左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。
    >> 右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。
    赋值运算符
    运算符 描述
    = 简单的赋值运算符,将一个表达式的值赋值给一个左值
    += 相加后再赋值
    -= 相减后再赋值
    /= 相除后再赋值
    %= 求余后再赋值
    <<= 左移后再赋值
    >>= 右移后再赋值
    &= 按位与后赋值
    ^= 按位异或后赋值
    |= 按位或后赋值
    *= 相乘后再赋值
    其他运算符
    运算符 描述 实例
    & 返回变量存储地址 &a;将给出变量的实际地址
    * 指针变量 *a;是一个指针变量
    运算符优先级

    优先级由高到低

    优先级 运算符
    7 ^ !
    6 * / % << >> & &^
    5 + - | ^
    4 == != < <= >= >
    3 <-
    &&
    1 ||


    Go语言条件语句

    if语句
    package main
    
    import "fmt"
    
    func main(){
    	//定义局部变量
    	var a int = 10
    	
        //使用 if 语句判断布尔表达式
    	if a < 20{
            //如果条件为true则执行以下语句
    		fmt.Printf("a 小于 20 
    ")
    	}
    	fmt.Printf("a的值为:%d 
    ",a)
    }
    
    输出结果
    a 小于 20 
    a的值为:10
    
    
    if ... else ...语句
    package main
    
    import "fmt"
    
    func main(){
    	//定义局部变量
    	var a int = 100
    
    	//判断布尔表达式
    	if a < 20{
    		//如果条件true,则执行以下语句
    		fmt.Printf("a 小于 20 
    ")
    	}else{
    		//如果条件false,则执行以下语句
    		fmt.Printf("a 不小于 20 
    ")
    	}
    	fmt.Printf("a的值为:%d 
    ",a)
    }
    
    输出结果
    a 不小于 20 
    a的值为:100 
    
    if嵌套语句
    package main
    
    import "fmt"
    
    func main(){
    	//定义局部变量
    	var a int = 100
    	var b int = 200
    
    	//判断布尔表达式
    	if a == 100{
    		//如果条件true,则执行以下语句
    		if b == 200{
    			//如果条件true,则执行以下语句
    			fmt.Printf("a 的值为 100, b 的值为 200
    ")
    		}
    	}
    	fmt.Printf("a的值为:%d 
    ",a)
    	fmt.Printf("b的值为:%d 
    ",b)
    }
    
    输出结果
    a 的值为 100, b 的值为 200
    a的值为:100 
    b的值为:200 
    
    
    Switch语句
    package main
    
    import "fmt"
    
    func main(){
    	//定义局部变量
    	var grade string = "B"
    	var marks int = 90
    
    	switch marks{
    	case 90: grade = "A"
    	case 80: grade = "B"
    	case 50,60,70 : grade = "C"
    	default:
    		grade = "D"
    	}
    	switch  {
    	case grade == "A":
    		fmt.Printf("优秀 
    ")
    	case grade == "B", grade == "C":
    		fmt.Printf("良好 
    ")
    	case grade == "D":
    		fmt.Printf("及格 
    ")
    	case grade == "F":
    		fmt.Printf("不及格 
    ")
    	default:
    		fmt.Printf("差 
    ")
    	}
    	fmt.Printf("你的等级是 %s 
    ",grade)
    	}
    
    输出结果
    优秀 
    你的等级是 A 
    
    
    Type Switch语句
    Type Switch语法格式
    	switch x.(type) {
    		case type:
    			statement(s);
    		case type:
    			statement(s);
    		default:
    			statement(s);
    	}
    
    package main
    
    import (
    	"fmt"
    )
    
    func main(){
    	var x interface{}
    
    	switch i:= x.(type) {
    	case nil:
    		fmt.Printf("x的类型 %T",i)
    	case int
    		fmt.Printf("x是int型")
    	case float64:
    		fmt.Printf("x是float64型")
    	case func(int) float64:
    		fmt.Printf("x是func(int)型")
    	case bool, string:
    		fmt.Printf("x是bool 或 string型")
    	default:
    		fmt.Printf("未知型")
    	}
    }
    
    输出结果
    x的类型 <nil>
    
    select语句

    select是Go中的一个控制结构,类似于用于通信的switch语句.每个case必须是一个通信操作,要么是发送要么是接收.

    select随机执行一个可运行的case,如果没有case可运行,它将阻塞,直到有case可运行,一个默认的子句应该是可运行的

    格式
    select {
        case communication clause :
        	statement(s);
        case communication clause :
        	statement(s);
        default:
       		statement(s);
    }
    
    • 每个case都必须是一个通信
    • 所有的channel表达式都会被求值
    • 所有被发送的表达式都会被求值
    • 如果任意某个通信可以进行,它就执行,其他被忽略
    • 如果有多个case都可以运行, select会随便公平地选出一个执行,其他不会执行
    • 否则:
      • 如果有default子句,则执行该语句
      • 如果没有default子句,select将阻塞,直到某个通信可以运行,Go不会重新对channel或值进行求值
    package main
    
    import "fmt"
    
    func main(){
    	var c1, c2, c3 chan int
    	var i1, i2 int
    	select {
    	case i1 = <-c1:
    		fmt.Printf("received ",i1," from c1 
    ")
    	case c2 <- i2:
    		fmt.Printf("sent ",i2," to c2 
    ")
    	case i3, ok := (<-c3):
    		if ok{
    			fmt.Printf("received ",i3, "from c3 
    ")
    		}else{
    			fmt.Printf("c3 is closed 
    ")
    		}
    	default:
    		fmt.Printf("no communication 
    ")
    	}
    }
    
    输出结果
    no communication 
    
    


    Go语言循环语句

    for循环

    for循环是一个循环控制结构,可以执行指定次数的循环

    for init; condition; post { }
    
    
    for codition { }
    
    
    for { }
    
    • init : 一般为赋值表达式,给控制变量赋初值
    • condition: 关系表达式或逻辑表达式,循环控制条件
    • post: 一般为赋值表达式, 给控制变量增加或减量

    for循环的range 格式可以对 slice, map ,数组, 字符串等进行迭代循环

    for key, value := range oldMap{
        newMap[key] = value
    }
    
    循环语句

    Go语言允许用户在循环内使用循环

    for [condition |  ( init; condition; increment ) | Range]
    {
       for [condition |  ( init; condition; increment ) | Range]
       {
          statement(s);
       }
       statement(s);
    }
    
    package main
    
    import "fmt"
    
    func main(){
    	//定义局部变量
    	var i,j int
    
    	for i = 2; i < 100; i++ {
    		for j = 2; j <= (i/j); j++{
    			if(i%j == 0){
    				break
    			}
    		}
    		if(j > (i/j)){
    			fmt.Printf("%d 是素数
    ",i)
    		}
    	}
    }
    
    

    break语句

    1. 用于循环语句中跳出循环, 并开始执行循环之后的语句
    2. break在switch(开关语句) 中在执行一条case后跳出语句的作用
  • 相关阅读:
    SpringBoot集成Redis
    独享锁 & 共享锁
    公平锁与非公平锁
    如何上传本地代码到码云
    SpringBoot+Mybatis+Pagehelper分页
    SpringBoot集成Mybatis(0配置注解版)
    高并发下接口幂等性解决方案
    SpringBoot全局配置文件
    干货
    Spring读取外部的资源配置文件—@PropertySource和@Value实现资源文件配置
  • 原文地址:https://www.cnblogs.com/mephisto03/p/9368762.html
Copyright © 2020-2023  润新知