Go语言学习笔记-Go语言基础语法

Go语言基础语法

1. 标识符与关键字

1.1 命名方式

  go变量、常量、自定义类型、包、函数的命名方式必须遵循以下规则:

  1. 首字符可以是任意Unicode字符或下划线。
  2. 首字符之外的部分可以是Unicode字符、下划线或数字。
  3. 名字的长度无限制。

理论上名字里可以有汉字,甚至可以全是汉字,但实际中不要这么做。

1.2 Go语言关键字

break  default  func  interface  select  case  defer  go  map  
struct  chan  else  goto  package  switch  const  if  range  type  
continue  for  import  return  fallthrough  var

1.3 保留字

常量

true  false  iota  nil   

数据类型

int  int8  int16  int32  int64  uint  uint8  uint16  uint32  uint64  uintptr  
float32  float64  complex128  complex64  bool  byte  rune  string  error

函数

make  len  cap  new  append  copy  close 
delete  complex  real  imag  panic  recover

2. 操作符与表达式

2.1 算法术运算符

运算符描述
+相加
-相减
*相乘
/相除
%求余
//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)
}

2.2 关系运算符

运算符描述
==检查两个值是否相等,如果相等返回 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)
	fmt.Printf("a!=b吗 %t\n", a != b)
	fmt.Printf("a>b吗 %t\n", a > b)
	fmt.Printf("a>=b吗 %t\n", a >= b)
	fmt.Printf("a<c吗 %t\n", a < b)
	fmt.Printf("a<=c吗 %t\n", a <= c)
}

2.3 逻辑运算符

运算符描述
&&逻辑 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)
	fmt.Printf("a>b || b>c吗 %t\n", a > b || b > c)
	fmt.Printf("a>b不成立,对吗 %t\n", !(a > b))
	fmt.Printf("b>c不成立,对吗 %t\n", !(b > c))
}

2.4 位运算符

运算符描述
&参与运算的两数各对应的二进位相与(两位均为1才为1)
|参与运算的两数各对应的二进位相或(两位有一个为1就为1)
^参与运算的两数各对应的二进位相异或,当两对应的二进位相同时为0,不同时为1。作为一元运算符时表示按位取反,,符号位也跟着变
<<左移n位就是乘以2的n次方。a<<b是把a的各二进位全部左移b位,高位丢弃,低位补0。通过左移,符号位可能会变
>>右移n位就是除以2的n次方。a>>b是把a的各二进位全部右移b位,正数高位补0,负数高位补1
//bit_op 位运算
func bit_op() {
	fmt.Printf("os arch %s, int size %d\n", runtime.GOARCH, strconv.IntSize) //int是4字节还是8字节,取决于操作系统是32位还是64位
	var a int32 = 260
	fmt.Printf("260     %s\n", util.BinaryFormat(a))
	fmt.Printf("-260    %s\n", util.BinaryFormat(-a)) //负数用补码表示。在对应正数二进制表示的基础上,按拉取反,再末位加1
	fmt.Printf("260&4   %s\n", util.BinaryFormat(a&4))
	fmt.Printf("260|3   %s\n", util.BinaryFormat(a|3))
	fmt.Printf("260^7   %s\n", util.BinaryFormat(a^7))     //^作为二元运算符时表示异或
	fmt.Printf("^-260   %s\n", util.BinaryFormat(^-a))     //^作为一元运算符时表示按位取反,符号位也跟着变
	fmt.Printf("-260>>10 %s\n", util.BinaryFormat(-a>>10)) //正数高位补0,负数高位补1
	fmt.Printf("-260<<3 %s\n", util.BinaryFormat(-a<<3))   //负数左移,可能变成正数
	//go语言没有循环(无符号)左/右移符号   >>>  <<<
}

位运算的应用场景:

  • 逻辑控制(运算快,省CPU)
  • bitmap和bloom filter(省内存)

总之,位运算适用于对性能要求高的场景。

func bit_application() {
	{
		var gender string = "男"
		var degree string = "本科"
		var is985 bool = true

		var condition1 bool = gender == "男"
		var condition2 bool = gender == "男" && is985
		var condition3 bool = gender == "男" && degree == "硕士" && is985
		fmt.Printf("满足条件1 %t\n", condition1)  //true
		fmt.Printf("满足条件2 %t\n", condition2)  //true
		fmt.Printf("满足条件3 %t\n", condition3)  //false
	}
	{
		var gender byte = 1      //末位,1:男,0:女
		var degree byte = 1 << 1 //倒数第二位,1:硕士,0:本科
		var is985 byte = 1 << 2  //倒数第三位,1:是985,2:不是985
		var man byte = gender | is985

		var condition1 byte = gender
		var condition2 byte = gender | is985
		var condition3 byte = gender | is985 | degree
		fmt.Printf("满足条件1 %t\n", man&condition1 == condition1)  //true
		fmt.Printf("满足条件2 %t\n", man&condition2 == condition2)  //true
		fmt.Printf("满足条件3 %t\n", man&condition3 == condition3)  //false
	}
}

2.5 赋值运算符

运算符描述
=简单的赋值运算符,将一个表达式的值赋给一个左值
+=相加后再赋值
-=相减后再赋值
*=相乘后再赋值
/=相除后再赋值
%=求余后再赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
|=按位或后赋值
^=按位异或后赋值
//assignment 赋值运算
func assignment() {
	var a, b int = 8, 3
	a += b
	fmt.Printf("a+=b %d\n", a)     //11
	a, b = 8, 3
	a -= b
	fmt.Printf("a-=b %d\n", a)       //5
	a, b = 8, 3
	a *= b
	fmt.Printf("a*=b %d\n", a)       //24
	a, b = 8, 3
	a /= b
	fmt.Printf("a/=b %d\n", a)       //2
	a, b = 8, 3
	a %= b
	fmt.Printf("a%%=b %d\n", a) //%在fmt里有特殊含意,所以需要前面再加个%转义一下   //2
	a, b = 8, 3
	a <<= b
	fmt.Printf("a<<=b %d\n", a)    //64
	a, b = 8, 3
	a >>= b
	fmt.Printf("a>>=b %d\n", a)    //1
	a, b = 8, 3
	a &= b
	fmt.Printf("a&=b %d\n", a)      //0
	a, b = 8, 3
	a |= b
	fmt.Printf("a|=b %d\n", a)      //11
	a, b = 8, 3
	a ^= b
	fmt.Printf("a^=b %d\n", a)     //11
}

3. 变量、常量、字面量

3.1 变量类型

类型go变量类型fmt输出
整型int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64%d(十进制) %b(二进制) %x(十六进制)
浮点型float32 float64%f %e %g
复数complex128 complex64%v
布尔型bool%t
指针uintptr%p
引用map slice channel%v
字节byte%c
任意字符rune%c %U(unicode编码)
字符串string%s
错误error%v
	fmt.Printf("%f\n", 3.14)      //3.140000
	fmt.Printf("%.4f\n", 3.14)    //3.1400
	fmt.Printf("%e\n", 3.14)      //3.140000e+00
	fmt.Printf("%g\n", 3.14)      //3.14
	fmt.Printf("%g\n", 3000000.0) //3e+06
	var a byte
	a = 'H'
	fmt.Printf("%c\n", a) //H
	var a rune
	a = '在'
	fmt.Printf("%U %c\n", a, a) //U+5728  在
	var b byte
	b = 97
	fmt.Printf("%d %c\n", b, b)   //97   a

3.2 变量声明

  Go语言变量必须先声明再使用,所谓使用指读取或修改。

标准声明

var name string 
var age int 
var isOk bool

批量声明

var ( 
	name string 
	age int 
	isOk bool 
)

3.3 变量初始化

  如果声明后未显式初始化,数值型初始化0,字符串初始化为空字符串,布尔型初始化为false,引用类型、函数、指针、接口初始化为nil。

var a string="china"  //初始化一个变量
var a="china"  //类型推断为string
var a,b int=3,7  //初始化多个变量
var a,b="china",7  //初始化多个变量,每个变量都单独地执行类型推断    

var a int
var b byte
var c float32
var d bool
var e string
fmt.Println(a, b, c, d, e) //0 0 0 false (空) 

  函数内部的变量(非全局变量)可以通过:=声明并初始化。

a:=3

  下划线表示匿名变量。匿名变量不占命名空间,不会分配内存,因此可以重复使用。

_=2+4

3.4 常量

  常量在定义时必须赋值,且程序运行期间其值不能改变。

const PI float32=3.14

const(
    PI=3.14
    E=2.71
)

const(
    a=100
    b	//100,跟上一行的值相同
    c	//100,跟上一行的值相同
)

const a int = 8
	fmt.Println(a) //8

	const (
		NAME   = "dws"
		GENDER = "male"
	)
	fmt.Printf("%s %s\n", NAME, GENDER)   //dws  male

iota

const(
    a=iota	//0
    b		//1
    c		//2
    d		//3
)

const(
    a=iota 	//0
    b		//1
    _		//2
    d		//3
)

const(
    a=iota 	//0
    b=30    
    c=iota 	//2
    d		//3
)

const(
    _=iota		// iota =0
    KB=1<<(10* iota) 	// iota =1
    MB=1<<(10* iota) 	// iota =2
    GB=1<<(10* iota) 	// iota =3
    TB=1<<(10* iota) 	// iota =4
)

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

3.5 字面量

  字面量–没有出现变量名,直接出现了值。基础类型的字面量相当于是常量。

fmt.Printf("%t\n", 04 == 4.00) //用到了整型字面量和浮点型字面量
fmt.Printf("%v\n", .4i) //虚数字面量 0.4i
fmt.Printf("%t\n", '\u4f17' == '众') //Unicode和rune字面量
fmt.Printf("Hello\nWorld\n!\n") //字符串字面量

var r rune
r = '众'
fmt.Printf("%t\n", r == '\u4f17')  //true

fmt.Print("Hello\nGolang\n你好")
Hello
Golang
你好

4. 变量作用域

  对于全局变量,如果以大写字母开头,所有地方都可以访问,跨package访问时需要带上package名称;如果以小写字母开头,则本package内都可以访问。
  函数内部的局部变量,仅本函数内可以访问。{}可以固定一个作用域。内部声明的变量可以跟外部声明的变量有冲突,以内部的为准–就近原则。

var (
    A=3	//所有地方都可以访问
    b=4	//本package内可以访问
)

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

import "fmt"

var (
	A = 7
	b = 4
)

func add(m int, n int) int {
	b := 5
	{
		//{}圈定了一个作用域
		b := 8
		fmt.Println(b) //8
	}
	fmt.Println(b)
	return m + n + b //就近原则

}

sub/foo.go
package sub

import "fmt"

func sub() {
	fmt.Println(A, b)     //引用同一个包中的全局变量

}


dir/d.go
package dir

import (
	"fmt"
	"week01/sub" //module_name/dir  //引用同一个文件的不同package包内容
)

func abc() {
	fmt.Println(sub.A)  

}

5. 注释与godoc

5.1 注释的形式

  • 单行注释,以//打头。
  • 多行注释有2种形式:
    1. 连续多行以//打头。
    2. 在段前使用/*,段尾使用*/。
  • 注意多行注释之间不能出现空行
  • 注释中给定的关键词。NOTE: 引人注意,TODO: 将来需要优化,Deprecated: 变量或函数强烈建议不要再使用。
  • 注释行前加缩进即可写go代码。
//Add 2个整数相加
//返回和。
//
//NOTE: 注释可以有多行,但中间不能出现空行(仅有//不算空行)。
func Add(a, b int) int {
	return a + b
}

/*
Sub 函数使用示例:
  for i:=0;i<3;i++{
	  Sub(i+1, i)
  }
看到了吗?只需要行前缩进,注释里就可以写go代码,是不是很简单。
*/
func Sub(a, b int) int {
	return a - b
}

//TODO: Prod 该函数不能并发调用,需要优化
func Prod(a, b int) int {
	return a * b
}

//Deprecated: Div 不要再调用了
func Div(a, b int) int {
	return a / b
}

5.2 注释的位置

  • 包注释:在package xxx的上方。一个包只需要在一个地方写包注释,通常会专门写一个doc.go,里面只有一行package xxx和关于包的注释。
  • 结构体的注释:在type xxx struct上方。
  • 函数注释:在func xxx()上方。
  • 行的注释:在行上方或右侧
// FormatBool, FormatFloat, FormatInt, and FormatUint convert values to strings:
//
//	s := strconv.FormatBool(true)
//	s := strconv.FormatFloat(3.1415, 'E', -1, 64)
//	s := strconv.FormatInt(-42, 16)
//	s := strconv.FormatUint(42, 16)
package fmt

sub/doc.go
/*
这是关于sub的第一行注释
这是关于sub的第二行注释
这是关于sub的第三行注释
 */
package sub

5.3 go doc

  go doc是go自带的命令。

go doc entrance_class/util
PS E:\Golang\week01> go doc sub
package sub // import "week01/sub"

这是关于sub的第一行注释 这是关于sub的第二行注释 这是关于sub的第三行注释

var A = 7 ...
PS E:\Golang\week01> 

上述命令查看entrance_class/util包的注释。

5.4 godoc

  godoc是第三方工具,可以为项目代码导出网页版的注释文档。安装godoc命令如下

go get -u golang.org/x/tools/cmd/godoc
go install golang.org/x/tools/cmd/godoc@latest

在这里插入图片描述
启动http服务:

godoc -http=:6060

在这里插入图片描述
用浏览器访问

  • http://127.0.0.1:6060
  • http://127.0.0.1:6060/pkg/<path>/<packagename>
  • http://127.0.0.1:6060/pkg/go-course/entrance_class/

可以查看go标准库的文档。
在这里插入图片描述
在这里插入图片描述第一空:c & a > 0
第二空:c >>= 1

package main

import (
	"fmt"
	"math"
	"strings"
)

func main() {
	var i int32
	i = 234567
	s := BinaryFormat(i)
	fmt.Println(s)
}

func BinaryFormat(n int32) string {
	a := uint32(n)
	sb := strings.Builder{}
	c := uint32(math.Pow(2, 31))
	for i := 0; i < 32; i++ {
		if c&a > 0 {
			sb.WriteString("1")
		} else {
			sb.WriteString("0")
		}
		c >>= 1
	}
	return sb.String()
}

PS E:\Golang\week01> go run .\hello.go
00000000000000111001010001000111

在这里插入图片描述

package main

import (
	"fmt"
	"math"
	"strings"
)

func main() {
	var i int32
	i = 234567
	s := BinaryFormat(i)
	fmt.Println(s)

	fmt.Println(CountOne(i))
}

func BinaryFormat(n int32) string {
	a := uint32(n)
	sb := strings.Builder{}
	c := uint32(math.Pow(2, 31))
	for i := 0; i < 32; i++ {
		if c&a > 0 {
			sb.WriteString("1")
		} else {
			sb.WriteString("0")
		}
		c >>= 1
	}
	return sb.String()
}

// 计算一个整数的二进制表示里含有几个1
func CountOne(n int32) int {
	cnt := 0
	a := uint32(n)
	var c uint32 = 1
	for i := 0; i < 32; i++ {
		if c&a > 0 { //说明a的最后一位是1(i=0)
			cnt += 1
		}
		c <<= 1
	}
	return cnt 
}
PS E:\Golang\week01> go run .\hello.go
00000000000000111001010001000111
9
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值