2、运算符、变量、常量、注释

一、Go语言的特点

  • Go语言类型:Go语言是强类型、静态编译型语言
    • 数据声明必须指定明确类型
    • 不支持隐式类型转换,类型转换必须强制
    • 代码编译成本地可执行代码,不需要虚拟机来运行
    • 支持垃圾回收

二、Go常用命令

  • go help:查看帮助文档go help build
  • go build:对源代码和依赖的文件进行打包,生成可执行文件go build -o my_first_go_exe entrance_class/demo.go
  • go install:编译并安装包或依赖,安装到$GOPATH/bin下go install entrance_class/demo.go
  • go get:把依赖库添加到当前module中
    • 如果本机之前从未下载过则先下载go get github.com/tinylib/msgp命令会在$GOPATH/pkg/mod目录下会生成github.com/tinylib/msgp目录
    • go install github.com/tinylib/msgp@latest命令会在$GOPATH/bin下生成msgp可执行文件
  • go mod init module_name:初始化一个Go项目
  • go mod tidy:go mod tidy通过扫描当前项目中的所有代码来添加未被记录的依赖至go.mod文件或从go.mod文件中删除不再被使用的依赖
  • go fmt:对代码文件进行格式化,如果用了IDE这个命令就不需要了go fmt entrance_class/demo.go
  • go doc:查看go标准库或第三方库的帮助文档
  • 库和二进制文件的位置
    • 下载的第三方依赖存储在$GOPATH/pkg/mod下
    • go install生成的可执行文件存储在$GOPATH/bin下
  • Go Modules依赖包的查找顺序
    • ①.工作目录
    • ②.$GOPATH/pkg/mod
    • ③.$GOROOT/src

三、运算符

  • 算法术运算符
运算符 描述
+ 相加
- 相减
* 相乘
/ 相除
% 求余
//arithmetic 算术运算
func arithmetic() {
	var a float32 = 8
	var b float32 = 3
	var c float32 = a + b
	var d float32 = a - b
	var e float32 = a * b
	var f float32 = a / b
	fmt.Printf("a=%.3f, b=%.3f, c=%.3f, d=%.3f, e=%.3f, f=%.3f\n", a, b, c, d, e, f)
	// a=8.000, b=3.000, c=11.000, d=5.000, e=24.000, f=2.667
}
  • 关系运算符
运算符 描述
== 检查两个值是否相等,如果相等返回 True 否则返回 False
!= 检查两个值是否不相等,如果不相等返回 True 否则返回 False
> 检查左边值是否大于右边值,如果是返回 True 否则返回 False
>= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False
< 检查左边值是否小于右边值,如果是返回 True 否则返回 False
<= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False
//relational 关系运算符
func relational() {
    
    
	var a float32 = 8
	var b float32 = 3
	var c float32 = 8
	fmt.Printf("a==b吗 %t\n", a == b) //false
	fmt.Printf("a!=b吗 %t\n", a != b) //true
	fmt.Printf("a>b吗 %t\n", a > b)   //true
	fmt.Printf("a>=b吗 %t\n", a >= b) //true
	fmt.Printf("a<c吗 %t\n", a < b)   //false
	fmt.Printf("a<=c吗 %t\n", a <= c) //true
}
  • 逻辑运算符
运算符 描述
& 逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False
|| 逻辑 OR 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False
! 逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True
//logistic 逻辑运算符
func logistic() {
    
    
	var a float32 = 8
	var b float32 = 3
	var c float32 = 8
	fmt.Printf("a>b && b>c吗 %t\n", a > b && b > c) //false
	fmt.Printf("a>b || b>c吗 %t\n", a > b || b > c) //true
	fmt.Printf("a>b不成立,对吗 %t\n", !(a > b))         //false
	fmt.Printf("b>c不成立,对吗 %t\n", !(b > c))         //true
}
  • 位运算符
运算符 描述
& 参与运算的两数各对应的二进位相与(两位均为1才为1)
| 参与运算的两数各对应的二进位相或(两位有一个为1就为1)
^ 参与运算的两数各对应的二进位相异或,当两对应的二进位相同时为0,不同时为1。作为一元运算符时表示按位取反,,符号位也跟着变
<< 左移n位就是乘以2的n次方。a<<b是把a的各二进位全部左移b位,高位丢弃,低位补0。通过左移,符号位可能会变
>> 右移n位就是除以2的n次方。a>>b是把a的各二进位全部右移b位,正数高位补0,负数高位补1
// 输出一个int32对应的二进制表示
func BinaryFormat(n int32) string {
    
    
	a := uint32(n)
	sb := strings.Builder{
    
    }
	c := uint32(math.Pow(2, 31)) //最高位上是1,其他位全是0
	for i := 0; i < 32; i++ {
    
    
		if a&c != 0 {
    
     //判断n的当前位上是否为1
			sb.WriteString("1")
		} else {
    
    
			sb.WriteString("0")
		}
		c >>= 1 //"1"往右移一位
	}
	return sb.String()
}

// bit_op 位运算
func bit_op() {
    
    
	//int是4字节还是8字节,取决于操作系统是32位还是64位
	fmt.Printf("os arch %s, int size %d\n", runtime.GOARCH, strconv.IntSize)

	var a int32 = 260
	fmt.Printf("260     %s\n", BinaryFormat(a)) //260     00000000000000000000000100000100

	//负数用补码表示。在对应正数二进制表示的基础上,按拉取反,再末位加1
	//另外一种办法:正数的二进制从右往左,在遇到第1个时都保持不变,之后的0转1,1转0,就可以算出负数补码
	fmt.Printf("-260    %s\n", BinaryFormat(-a))  //-260    11111111111111111111111011111100
	fmt.Printf("260&4   %s\n", BinaryFormat(a&4)) //260&4   00000000000000000000000000000100
	fmt.Printf("260|3   %s\n", BinaryFormat(a|3)) //260|3   00000000000000000000000100000111

	//^作为二元运算符时表示异或
	fmt.Printf("260^7   %s\n", BinaryFormat(a^7)) //260^7   00000000000000000000000100000011
	//^作为一元运算符时表示按位取反,符号位也跟着变
	fmt.Printf("^-260   %s\n", BinaryFormat(^-a)) //^-260   00000000000000000000000100000011
	//正数高位补0,负数高位补1
	fmt.Printf("-260>>10 %s\n", BinaryFormat(-a>>10)) //-260>>10 11111111111111111111111111111111

	//负数左移,可能变成正数
	fmt.Printf("-260<<3 %s\n", BinaryFormat(-a<<3)) //-260<<3 11111111111111111111011111100000
}

四、变量

  • go的变量类型
    • %e:科学计数法
    • %g:在f和e中自动选择最合适的
类型 go变量类型 fmt输出
整型 int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 %d
浮点型 float32 float64 %f %e %g
复数 complex128 complex64 %v
布尔型 bool %t
指针 uintptr %p
引用 map slice channel %v
字节 byte %c
任意字符 rune %c
字符串 string %s
错误 error %v
package main

import "fmt"

func main() {
    
    
	a := 500000000000.0
	fmt.Printf("%f\n", a) // 500000000000.000000
	fmt.Printf("%e\n", a) // 5.000000e+11
	fmt.Printf("%g\n", a) // 5e+11
}
  • %v占位符
package main

import "fmt"

func main() {
    
    
	type User struct {
    
    
		Name string
		Age  int
	}
	user := &User{
    
    "zhang san", 4}

	fmt.Printf("%v\n", user)  //&{zhang san 4}
	fmt.Printf("%+v\n", user) //&{Name:zhang san Age:4}
	fmt.Printf("%#v\n", user) //&main.User{Name:"zhang san", Age:4}

}

  • %在fmt中的转义
package main

import (
	"fmt"
)

func main() {
    
    
	a := 1
	b := 2
	fmt.Printf("a%%=b %d\n", a%b) //%在fmt里有特殊含意,所以需要前面再加个%转义一下
}

  • 变量初始化:如果声明后未显式初始化
    • 数值型初始化0
    • 字符串初始化为空字符串
    • 布尔型初始化为false
    • 引用类型、函数、指针、接口初始化为nil
var a string="china"  //初始化一个变量
var a="china"  //类型推断为string
var a,b int=3,7  //初始化多个变量
var a,b="china",7  //初始化多个变量,每个变量都单独地执行类型推断 
  • 函数内部的变量(非全局变量)可以通过:=声明并初始化a:=3
  • 下划线表示匿名变量。匿名变量不占命名空间,不会分配内存,因此可以重复使用_=2+4
  • go中的++--运算符要求
    • 只能使用后置的++--
    • 只能独立一行,不能放在表达式中
func main() {
    
    
	a := 1
	a++ //right
	fmt.Println(a++) //wrong
}
  • 变量作用域
    • 对于全局变量,如果以大写字母开头,所有地方都可以访问,跨package访问时需要带上package名称
    • 如果以小写字母开头,则本package内都可以访问
    • 函数内部的局部变量,仅本函数内可以访问
    • 内部声明的变量可以跟外部声明的变量有冲突,以内部的为准–就近原则
var (
	A = 3 //所有地方都可以访问
	b = 4 //本package内可以访问
)

func foo() {
    
    
	b := 5 //本函数内可以访问
	{
    
    
		b := 6 //本作用域内可以访问
	}
}

五、常量

  • 常量:Go语言的常量定义,必须是能在编译器就要完全确定其值,所以值只能使用字面常量
    • 数组不可以在Go中定义常量,因为数组的元素可变
    • 切片不可以在Go中定义常量,因为切片不仅元素可变,切片的长度也可变
      在这里插入图片描述
  • 字面量:没有出现变量名,直接出现了值。基础类型的字面量相当于是常量
func main() {
    
    
	fmt.Printf("%t\n", 04 == 4.00)      //用到了整型字面量和浮点型字面量 -> true
	fmt.Printf("%v\n", .4i)             //虚数字面量 0.4i -> (0+0.4i),实部是0,虚部是0.4
	fmt.Printf("%t\n", '\u4f17' == '众') //Unicode和rune字面量 -> true
	var r rune = '众'                    //type rune = int32
	fmt.Printf("%d %x\n", r, r)         // 20247 4f17

	fmt.Printf("Hello\nWorld\n!\n") //字符串字面量
}
  • iota
    • 如果不是批量的时候,iota每次总是从0开始
    • 批量中iota总是从第1行开始,即使不使用也会每行+1
    • 批量中都是同一个iota
package main

import "fmt"

func main() {
    
    
	const a = iota
	const b = iota
	fmt.Println(a, b) //0 0
	const (
		c = iota
		d
		e
	)
	fmt.Println(c, d, e) //0 1 2

	const (
		l = iota
		_
		_
		m
	)
	fmt.Println(l, m) //0 3

	const (
		x = iota
		y
		z = iota
		u
	)
	fmt.Println(x, y, z, u) //0 1 2 3

	const (
		i = iota
		_
		j = iota + 10
		k
	)
	fmt.Println(i, j, k) //0 12 13

	const (
		v = 10
		h
		n = iota //批量中的iota总是从0开始
	)
	fmt.Println(v, h, n) // 10 10 2

	const (
		o = iota
		p = 10
		q
		r = iota //批量里面的iota都是同一个
	)
	fmt.Println(o, p, q, r) //0 10 10 3

	const(
     a,b=iota+1, iota+2	//1,2  iota =0
     c,d			//2,3  iota =1
     e,f			//3,4  iota =2
	)
}

  • 使用iota定义偶数和奇数
func main() {
    
    
	const (
		a = iota * 2
		b
		c
		d
	)
	fmt.Println(a, b, c, d) //0 2 4 6

	const (
		l = iota*2 + 1
		m
		n
		o
	)
	fmt.Println(l, m, n, o) //1 3 5 7
}

六、注释与godoc

  • 注释:Go的标准库源码多行注释写法采用的是每行使用//
    • ①.单行注释://
    • ②.多行注释:/* */
      在这里插入图片描述
// test函数的作用:
// 参数a类型的作用,
// 参数b类型的作用,
// 参数c类型的作用
func test(a int,b string,c bool){
    
    

}
  • 特殊含义的注释
    • // TODO:将来需要优化或完成的功能
    • // NOTE:需要注意的地方
    • // Deprecated:已经过期,建议不要使用;未来某个版本可能移除
  • go doc:go doc是go自带的命令
    • go doc entrance_class/util:查看entrance_class/util包的注释
  • godoc:godoc(这个是没有空格的,与go doc不同)可以为项目代码导出网页版的注释文档

猜你喜欢

转载自blog.csdn.net/qq23001186/article/details/128864515