1、Go核心编程(基础部分)

编程入门 行业动态 更新时间:2024-10-26 16:26:07

1、Go<a href=https://www.elefans.com/category/jswz/34/1769673.html style=核心编程(基础部分)"/>

1、Go核心编程(基础部分)

Go入门介绍

Golang特点

Go语言既能达到静态语言的安全和性能,又达到了动态语言开发维护的高效,使用一个表达式来形容Go语音(Go = C + Python),说明Go语言既有C静态语言程序的运行速度,又能达到Python动态语言的快速开发。
1、go从C语言中继承了很多理念,包括表达式语法、控制结构、基础数据类型、调用参数传值、指针(弱化指针)等,也保留了和C语言一样的编译执行方式。
2、函数可以返回多个值
3、引入包的概念,用于组织程序结构,Go语言的一个文件都要归属于一个包,而不能单独存在。
4、垃圾回收机制,内存自动回收,不需要开发人员管理。
5、天然并发

  • 从语言层面支持并发,实现简单
  • goroutine,轻量级线程,可实现大并发处理,高效利用多核
  • 基于CPS并发模型实现

6、吸收了管道通信机制,形成Go语言特有的channel,通过管道channel,可以实现不同的goroute之间的相互通信
7、新的创新,比如切片slice,延时执行defer等

Golang操作(入门级)

1、GO程序执行go build go1.go --> go1.exe通过go build生成可执行文件.exe,然后执行可执行文件即可go run go1.go 通过go run 直接执行,需要电脑有go的环境,不会生成其他文件
2、Go语法要求每条语句不需要分号结尾,因此,一行也只能有一条语句导入的包或者是定义的变量如果没有使用到会报错,无法通过编译( 如果没有使用fmt中的函数--> imported and not used: "fmt")缩进是一次tab键,没有缩进不会出现语法错误,仅是格式不对注释和c语言一样函数左侧花括号不能独立一行,否则会报错。只能是和函数名同一行,然后换行写语句。# command-line-arguments.\go1.go:19:1: syntax error: unexpected semicolon or newline before {
3、格式化代码gofmt go1.go 可以将该文件中的代码格式化之后输出到控制台gofmt -w go1.to 可以将文件中的代码格式化之后写入到文件中

Golang变量

1、变量使用步骤

变量使用步骤声明变量(定义变量)基本语法:var 变量名 数据类型比如,var a int声明一个int类型的变量a初始化变量在声明变量的时候就赋值var a int = 90 这就是初始化变量a。细节:如果声明的时候就直接赋值,可以省略数据类型(自动推导类型)var b = 99变量赋值如果只是声明了变量:var num int //默认值为0然后再给值num = 99这就是赋值。

2、局部变量的使用方式

第一种:指定变量类型,声明后若不赋值,使用默认值

package main
import "fmt"func main() {//这种方式相当于直接使用定义了一个变量,使用他的默认值var i intfmt.Println("i = ", i)var f float64fmt.Println("f = ", f)var s stringfmt.Println("s = ", s, "s ==\"\" ?", s == "")
}

第二种:根据值自行判定变量类型(类型推导)
这种方式下必须在定义的时候赋值,不能后期赋值。这种方式也不存在默认值一说,因为一开始就要手动赋值,否则会报错。

package main
import "fmt"func main() {var i = 98fmt.Println("i = ", i)var s = "你好"fmt.Println("s = ", s)}

错误情况

第三种:省略 var, 注意 :=左侧的变量不能是已经声明过的,否则会导致编译错误。
这种方式既然省略了var关键字,就不能再使用它,否则会报错。

package main
import "fmt"func main() {//相当于 var name string 	name= "kiko"name := "kiko"fmt.Println("name: ", name)}

总结三种变量的使用方式。
基于基本语法 var + 变量名 + 数据类型的语法格式,第一种是标准的格式;第二种则是省略数据类型,因为这个变量可以在声明的时候赋初值(自动类型推导),当然此处不省略数据类型也可以,但是必须赋初值;第三种则是在var上做文章,var也可以省略,但是必须要使用:=的形式,且要赋初值,这里的var就必须要省略。
综上,除了第一种标准的格式,其他两种都是在var和数据类型上面做省略,且两者的共同点就是必须要赋初值

一次性声明多个变量
声明多个变量的从上面三种方式引申而出。

package main
import "fmt"func main() {//多变量声明方式1(基本形式,只能是一种类型)var n1, n2, n3 int	n1 = 99fmt.Println("n1 = ", n1, "n2 = ", n2, "n3 = ", n3)	//n1 =  99 n2 =  0 n3 =  0//多变量声明方式2(省略数据类型)var n4, psw, distance = 190, "admin", 99.99fmt.Println("n4 =", n4, "psw =", psw, "distance =", distance) //n4 = 190 psw = admin distance = 99.99//多变量声明方式3(省略var)n5, n6, n7 := 999, 99.99, "vovo"fmt.Println("n5 =", n5, "n6 =", n6, "vovo =", n7)
}

3、全局变量的使用方式

全局变量和局部变量的使用方式基本相同,前两种方式是一样的,但是全局变量没有 := 定义的方式,此外全局变量可以定义在一起,共用一个var关键字。
全局变量在使用过程中通常都是设置了一个初始值,一般不会只声明全局变量。

package main
import "fmt"func main() {//输出全局变量fmt.Println("gn1 = ", gn1, "gn2 =", gn2, "gn3 =", gn3, "gn4 =", gn4, "gn5 =", gn5, "gn6 =", gn6)}/*全局变量可以定义在使用了全局变量函数的后面
*///定义全局变量
var gn1 = 100
var gn2 = 888.888
var gn3 = "yoyo"//上面的声明方式可以改成一次性声明
var (gn4 = 500gn5 = 999.999gn6 = "kiko"
)

4、变量使用的注意事项

  • 变量 = 变量名 + 数据类型 + 数值缺一不可。
  • Golang的变量如果没有赋初值,编译器会使用默认值,比如 int 默认值 0 ,string 默认值为空串,即"",小数默认为 0。
  • 变量在同一个作用域(在一个函数或者在代码块)内不能重名。

5、程序中的+号

  • 当左右两边都是数值型时,则做加法运算
  • 当左右两边都是字符串,则做字符串拼接
package main
import "fmt"func main() {//数值类型的 + var i = 10// var f = 19.9	//这里测试要注释掉,因为没有使用到f这个变量,否则编译出错var i1 = 20//两种不同的数值类型不能做 加法运算,这里的i + f是无法通过编译的var res1 = i + i1fmt.Println(" i + f = ", res1,)//字符串name := "kiko"friend := "yoyo"res2 := name + friendfmt.Println("name + friend = ", res2)}

Golang数据类型(基本类型)

1、数据类型分类

2、整型

第一种、有符号整数

第二种、无符号整数

第三种、其他整数类型

使用对应的类型,数值就不能超过类型限定的值,否则无法编译通过。

整型的使用细节

  • Golang 各整数类型分:有符号和无符号,int uint 的大小和系统有关。
  • Golang 的整型默认声明为 int 型,就是自动推导的类型。
  • 查看变量类型和所占子节大小
  • Golang 程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型。【如:年龄,使用byte类型就足够了】
  • bit: 计算机中的最小存储单位。byte:计算机中基本存储单元。

3、小数类型/浮点型

  1. 类型分类(都是有符号的)
package main
import ("fmt""unsafe"
)func main(){var f float32 = 10.2000001fmt.Println("f = ", f)fmt.Printf("type = %T, size = %d\n", f, unsafe.Sizeof(f))var d = 123.898323212	//默认自动推导到float64fmt.Println("d = ", d)fmt.Printf("type = %T, size = %d\n", d, unsafe.Sizeof(d))
}
  1. 类型说明
    关于浮点数在机器中存放形式的简单说明,浮点数=符号位+指数位+尾数位
    尾数部分可能丢失,造成精度损失。
    浮点型的存储分为三部分:符号位+指数位+尾数位 在存储过程中,精度会有丢失。

  2. 使用细节

Golang 浮点类型有固定的范围和字段长度,不受具体OS(操作系统)的影响。
Golang 的浮点型默认声明为 float64 类型。
浮点型常量有两种表示形式:十进制数形式:如:5.12 .512 (必须有小数点)科学计数法形式:如:5.1234e2 = 5.1234 * 10 的 2 次方 5.12E-2 = 5.12/10 的 负2次方
通常情况下,应该使用 float64 ,因为它比 float32 更精确。[开发中,推荐使用 float64]
package main
import ("fmt""unsafe"
)func main() {//十进制形式:如 5.12   .512(必须有小数点)num1 := 5.12num2 := .512fmt.Println("num1: ", num1, " num2: ", num2)fmt.Printf("num1 type %T: num1 size %d\n", num1, unsafe.Sizeof(num1))//科学计数法形式num3 := 5.1234e2num4 := 5.1234E2num5 := 5.1234E-2fmt.Println("num3: ", num3, " num4: ", num4, " num5: ", num5)fmt.Printf("num3 type %T: num3 size %d\n", num3, unsafe.Sizeof(num3))}

4、字符类型

***基本介绍
go语言中没有专门的类型用来存储字符。如果要存储单个字符(字母),一般使用 byte 来保存。
字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。也就是说对于传统的字符串是由字符组成的,而 Go 的字符串不同,它是由字节组成的

package main
import("fmt"
)func main() {var c byte = 'a'var z byte = '0'//直接输出变量是输出字符对应的码值fmt.Println("c = ", c, " z = ", z)//使用格式化输出可以输出字符串fmt.Printf("c = %c, z = %c\n", c, z)// var x byte = '你'  //overflows bytevar x int = '你'fmt.Println("x = ",	 x)}


说明:
如果我们保存的字符在 ASCII 表的,比如[0-1, a-z,A-Z…]直接可以保存到 byte
如果我们保存的字符对应码值大于 255,这时我们可以考虑使用 int32(rune) 类型保存
如果我们需要安装字符的方式输出,这时我们需要格式化输出,即 fmt.Printf(“%c”, c1)…

*** 字符类型使用的细节
1、字符常量是用单引号(‘’)括起来的单个字符。例如:var c1 byte = 'a' ; var c2 int = '中' ; var c3 byte = '9'
2、Go 中允许使用转义字符 '\’来将其后的字符转变为特殊字符型常量。例如:var c3 char = ‘\n’ // '\n’表示换行符
3、 Go 语 言 的 字 符 使 用 UTF-8 编码,英文字母-1 个字节 汉字-3 个字节
4、在 Go 中,字符的本质是一个整数,直接输出时,是该字符对应的 UTF-8 编码的码值。
5、可以直接给某个变量赋一个数字,然后按格式化输出时%c,会输出该数字对应的 unicode 字符。
6、字符类型是可以进行运算的,相当于一个整数,因为它都对应有 Unicode 码。
7、其实可以用整型中的rune类型,int类型有8个子节点(64位系统)有点大了。

package main
import("fmt"
)func main() {// var x byte = '你'  //overflows bytevar x int = '你'fmt.Println("x = ",	 x)//字符运算var ch byte = 'a'var chs = ch + 10fmt.Println("chs = ", chs)fmt.Printf("chs = %c\n", chs)}


***字符类型本质探讨
1、字符型 存储到 计算机中,需要将字符对应的码值(整数)找出来
存储:字符—>对应码值---->二进制–>存储
读取:二进制----> 码值 ----> 字符 --> 读取
2、字符和码值的对应关系是通过字符编码表决定的(是规定好)
3、Go 语言的编码都统一成了 utf-8。非常的方便,很统一,再也没有编码乱码的困扰了。

5、布尔类型

***基本介绍
1、布尔类型也叫bool类型,bool类型数据只允许取值true和false
2、bool类型占1个子节
3、bool类型适用于逻辑运算,一般用于程序流程控制。

package main
import("fmt""unsafe"
)func main() {var b boolfmt.Println("b = ", b)		//默认值为falsevar b1 = truefmt.Println("b1 = ", b1)fmt.Printf("b type = %T, b size = %d\n", b, unsafe.Sizeof(b))}

6、字符串类型

***基本介绍
字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。

package main
import ("fmt""unsafe"
)func main(){name := "你好 Golang"fmt.Println(name)fmt.Printf("type = %T, size = %d\n", name, unsafe.Sizeof(name))
}

*** string 使用注意事项和细节
1、Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本,这样 Golang 统一使用 UTF-8 编码,中文乱码问题不会再困扰程序员。
2、字符串一旦赋值了,字符串就不能修改字符串内部的元素了;在 Go 中字符串是不可变的。但是可以重新整体赋值。
3、字符串的两种表示形式
第一、双引号, 会识别转义字符
第二、反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果

package main
import ("fmt"// "unsafe"
)func main(){//双引号形式,可以识别转义字符\nname := "你好\nGolang"	fmt.Println(name)//使用反引号,按照字符串原样输出user := `		package mainimport ("fmt""unsafe")func main() {//十进制形式:如 5.12   .512(必须有小数点)num1 := 5.12num2 := .512fmt.Println("num1: ", num1, " num2: ", num2)fmt.Printf("num1 type %T: num1 size %d\n", num1, unsafe.Sizeof(num1))//科学计数法形式num3 := 5.1234e2num4 := 5.1234E2num5 := 5.1234E-2fmt.Println("num3: ", num3, " num4: ", num4, " num5: ", num5)fmt.Printf("num3 type %T: num3 size %d\n", num3, unsafe.Sizeof(num3))}`fmt.Println(user)}


4、字符串拼接
字符串拼接使用+号,如果一行字符串太长可以换行拼接。

package main
import ("fmt"
)func main(){str := "hello world" + " HELLO Golang"fmt.Println(str)//分行连接, +号必须在行尾,而不能是下一行开头nstr := "HELLO Golang" + " HELLO Go" +" fmt" + "YOYO" + " MM"fmt.Println(nstr)
}

7、基本数据类型默认值


8、基本数据类型(数值)的相互转换

*** 基本介绍
Golang 和 java / c 不同,Go 在不同类型的变量之间赋值时需要显式转换。也就是说 Golang 中数据类型不能自动转换。

*** 基本语法
表达式 T(v) 将值 v 转换为类型 T
T: 就是数据类型,比如 int32,int64,float32 等等
v: 就是需要转换的变量(变量名)

package mainimport ("fmt"// "unsafe"
)func main() {//T(v)var i int32 = 100//希望将 i ==> floatvar n1 float32 = float32(i)	var n2 int8 = int8(i)		//高精度转低精度var n3 int64 = int64(i)		//低精度转高精度fmt.Printf("i = %v, n1 = %v, n2 = %v, n3 = %v\n", i, n1, n2, n3)}


*** 基本数据类型相互转换的注意事项
1、Go 中,数据类型的转换可以是从 范围小–>范围大,也可以 范围大—>范围小。
2、被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化!也就是不会影响被转换的变量的本身。
3、在转换中,比如将 int64 转成 int8 【-128—127】 ,编译时不会报错,只是转换的结果是按溢出处理,和我们希望的结果不一样(其他语言也是这么处理的)。 因此在转换时,需要考虑范围,这种情况只可能出现在高精度转低精度。

package mainimport ("fmt"// "unsafe"
)func main() {//T(v)var i int64 = 8888//希望将 int64 --> int8var n1 int8 = int8(i)		//高精度转低精度fmt.Printf("i = %v, n1 = %v\n", i, n1)}


4、其他细节(关于不同类型计算)
不同类型之间无法计算,即使同为整型,因为具体的类型不一致也会报错。

package mainimport ("fmt"// "unsafe"
)func main() {var n1 int32 = 12var n2 int64var n3 int8//下面是错误写法(编译报错),类型是虽然都是整型,但是类型还是不一致的,必须完全一致才可以。返回的类型和计算的变量的类型必须一致,且计算的两个都是变量,这两个变量也必须类型一致。如果计算的都是常量,那么不会出现问题,返回值会自动匹配返回类型。// n2 = n1 + 20// n3 = n1 + 20//这种写法可以。常量20可以自动匹配类型,n1就要转换成和n2、n3一致的类型才可以计算n2 = int64(n1) + 20	n3 = int8(n1) + 20fmt.Println(n1, n2, n3)
}

两种执行情况

package mainimport ("fmt"// "unsafe"
)func main() {var n1 int32 = 12var n2 int8var n3 int8// int8类型最大值是127n2 = int8(n1) + 127	//编译通过,但是结果按照溢出处理// n3 = int8(n1) + 128	//编译无法通过,因为128和int8类型不匹配。fmt.Println(n1, n2, n3)
}

9、基本数据类型(数值)和string类型转换

*** 基本介绍
在实际开发过程中,通常需要将字符串转成基本数据类型,或者将基本数据类型的数值当成字符串处理。

***基本类型转string类型
1、方式一:fmt.Sprintf(“%参数”, 表达式)

参数需要和表达式的数据类型相匹配
fmt.Sprintf()… 会返回转换后的字符串

package mainimport ("fmt"
)func main() {//方式1、fmt.Sprintf("%参数", 表达式)var num1 int = 99var num2 float64 = 23.36989var b bool = truevar ch byte = 'H'var str stringstr = fmt.Sprintf("%d", num1)fmt.Printf("str type %T str = %q\n", str, str)str = fmt.Sprintf("%f", num2)fmt.Printf("str type %T str = %q\n", str, str)str = fmt.Sprintf("%t", b)fmt.Printf("str type %T str = %q\n", str, str)str = fmt.Sprintf("%c", ch)fmt.Printf("str type %T str = %q\n", str, str)
}


2、方式二:使用时 strconv 包的函数

package mainimport ("fmt"// "unsafe""strconv"
)func main() {//使用strconv包里的函数var num1 int = 99var num2 float64 = 12.3659var b2 bool = true//1、func FormatInt(int64, int) string --> 第一个参数必须是int64,第二个参数是进制str := strconv.FormatInt(int64(num1), 10)	//10进制fmt.Printf("str type %T str = %q\n", str, str) //%q表示输出的字符串会用""括起来str = strconv.FormatInt(int64(num1), 2)		//2进制fmt.Printf("str type %T str = %q\n", str, str)//2、func FormatFloat(float64, byte, prec, bitSize) string//第一个参数必须是要转换的浮点型,且是float64//第二个参数是格式,小数形式还是科学计数法形式;第三个参数表示小数点后保留位数//第四个参数表示这个小数是float64类型的str = strconv.FormatFloat(num2, 'f', 10, 64)fmt.Printf("str type %T str = %q\n", str, str)//3、func FormatBool(bool) stringstr = strconv.FormatBool(b2)fmt.Printf("str type %T str = %q\n", str, str)//4、func Itoa(i int) string//Itoa 内部直接调用 FormatInt(i, 10) 实现的var num5 int64 = 4567str = strconv.Itoa(int(num5))fmt.Printf("str type %T str = %q\n", str, str)}

*** string类型转基本类型
使用strconv包中的ParseXXX函数即可

package mainimport ("fmt"// "unsafe""strconv"
)func main() {var str string = "true"var b bool//1. strconv.ParseBool(str)(bool, error)函数返回两个值,参数一个字符串//因为只要获取到bool value,不想获取error,所以可以使用 _ 忽略b, _ = strconv.ParseBool(str)fmt.Printf("b type %T, b = %v\n", b, b)//2. strconv.ParseInt(string, base int, bitSize int)(int64, error)var str2 string = "123456"var n1 int64var n2 intn1, _ = strconv.ParseInt(str2, 10, 64)n2 = int(n1)fmt.Printf("n1 type %T, n1 = %v\n", n1, n1)fmt.Printf("n2 type %T, n2 = %v\n", n2, n2)//3. strconv.ParseFloat(string, bitSize)(float64, error)var str3 string = "12.45"var f1 float64f1, _ = strconv.ParseFloat(str3, 64)fmt.Printf("f1 type %T, f1 = %v\n", f1, f1)
}

***string 转基本数据类型的注意事项
在将 String 类型转成 基本数据类型时,要确保 String 类型能够转成有效的数据,比如 我们可以把 “123” , 转成一个整数,但是不能把 “hello” 转成一个整数,如果这样做,Golang 直接将其转成 0 ,其它类型也是一样的道理. float => 0 bool => false。

package mainimport ("fmt""strconv"
)func main() {var str string = "HELLO"var n int64 = 11n, _ = strconv.ParseInt(str, 10, 64)fmt.Printf("n type %T, n = %v\n", n, n)
}

10、指针类型

***基本介绍
1、基本数据类型,变量存的就是值,也叫值类型。
2、每个变量都有一个地址,要获取变量的地址,用&,比如:var num int,获取num的地址:&num。
3、指针类型,指针变量存的是一个地址值,这个地址指向的空间存的才是值。
比如:var ptr *int = &num(不能直接用一个数值赋给指针变量)
4、获取指针类型所指向的值,使用:*,比如:var ptr int,使用ptr获取ptr指向空间的存的值。

package mainimport ("fmt"// "strconv"
)func main() {var i int = 90fmt.Println("i变量的地址 ", &i)fmt.Println("i变量的值 = ", i)var ptr_i *int = &ifmt.Println("ptr_i = ", ptr_i)fmt.Println("ptr_i 指针指向的值= ", *ptr_i)*ptr_i = 100		//修改指向的值fmt.Println("i变量的地址 ", &i)fmt.Println("i变量的值 = ", i)fmt.Println("ptr_i = ", ptr_i)fmt.Println("ptr_i 指针指向的值= ", *ptr_i)}


*** 指针使用细节
1、值类型,都有对应的指针类型,形式为: *数据类型,比如int的对应的指针就是*int,其他类型依次类推。
2、值类型包括:基本数据类型int系列,float系列,bool,string,数组和结构体struct

11、值类型和引用类型

值类型:基本数据类型 int 系列, float 系列, bool, string 、数组和结构体 struct。
引用类型:指针、slice 切片、map、管道 chan、interface。

***值类型和引用类型的使用特点
1、值类型
变量直接存储值,内存通常在中分配。

2、引用类型
变量存储的是一个地址,这个地址对应的空间才真正存储数据(值),内存通常在上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由 GC 来回收。

Golang中的标识符和占位符

1、标识符

*** 标识符的概念
Golang 对各种变量、方法、函数等命名时使用的字符序列称为标识符。
凡是自己可以起名字的地方都叫标识符。

*** 标识符的命名规则
1、 由 26 个英文字母大小写,0-9 ,_ 组成
2、 数字不可以开头。var num int //ok var 3num int //error
3、 Golang 中严格区分大小写。
4、标识符不能包含空格。
5、下划线"_"本身在 Go 中是一个特殊的标识符,称为空标识符。可以代表任何其它的标识符,但是它对应的值会被忽略(比如:忽略某个返回值)。所以仅能被作为占位符使用,不能单独作为标识符使用。在函数返回值时,若是不要其中某一个返回值,可以使用 _ 将其忽略。
6、不能以系统保留关键字作为标识符(一共有 25 个)

*** 标识符命名注意事项
1、包名:保持 package 的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,不要和标准库冲突,如 fmt。
2、变量名、函数名、常量名:采用驼峰法
3、如果变量名、函数名、常量名首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用 ( 注:可以简单的理解成,首字母大写是公开的,首字母小写是私有的) ,在 golang 没有public , private 等关键字。

2、占位符(格式化输出)

*** 普通占位符

%v	the value in a default formatwhen printing structs, the plus flag (%+v) adds field names
%#v	a Go-syntax representation of the value
%T	a Go-syntax representation of the type of the value
%%	a literal percent sign; consumes no value

*** 布尔类型

%t	the word true or false

*** 整型

%b	base 2
%c	the character represented by the corresponding Unicode code point
%d	base 10
%o	base 8
%O	base 8 with 0o prefix
%q	a single-quoted character literal safely escaped with Go syntax.
%x	base 16, with lower-case letters for a-f
%X	base 16, with upper-case letters for A-F
%U	Unicode format: U+1234; same as "U+%04X"

*** 浮点型

%b	decimalless scientific notation with exponent a power of two,in the manner of strconv.FormatFloat with the 'b' format,e.g. -123456p-78
%e	scientific notation, e.g. -1.234456e+78
%E	scientific notation, e.g. -1.234456E+78
%f	decimal point but no exponent, e.g. 123.456
%F	synonym for %f
%g	%e for large exponents, %f otherwise. Precision is discussed below.
%G	%E for large exponents, %F otherwise
%x	hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20
%X	upper-case hexadecimal notation, e.g. -0X1.23ABCP+20

*** 字符串和切片

%s	the uninterpreted bytes of the string or slice
%q	a double-quoted string safely escaped with Go syntax
%x	base 16, lower-case, two characters per byte
%X	base 16, upper-case, two characters per byte

*** 指针

%p	address of 0th element in base 16 notation, with leading 0x

3、系统保留关键字和预定义标识符

Golang中的运算符

1、运算符基本介绍

运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等

  1. 算术运算符
  2. 赋值运算符
  3. 比较运算符/关系运算符
  4. 逻辑运算符
  5. 位运算符
  6. 其它运算符
    Golang中没有三元运算符

2、数值计算问题(插入)

在学习算术运算符之前,需要先了解一下数值之间的计算问题,上面也提到过,不同类型的数值不能计算,但是说的比较笼统,当时也没去深入了解。现在做以下总结。
主要分为三种情况:
1、返回值 = 常量 + 常量
2、返回值 = 常量 + 变量
3、返回值 = 变量 + 变量

*** 第一种情况

package mainimport ("fmt"
)func main() {/*1、返回值 = 常量 + 常量要求:常量显式的值必须是返回值能够接受的类型。但是也有例外,比如 var x int = 10.0 / 10	10.0显然不是int能够接受的,但是因为小数点后面是0所以也可以接受这种情况注意:整型本身就可以接受小数点后面全是0情况的数,正因为此,上面的情况才可以执行。*/var x int32 = 10 * 10fmt.Println(x)x = 10.0fmt.Printf("x type = %T, x = %d\n", x, x)x = 10.0 / 10fmt.Println(x)//x = 10.1 / 10	  // 10.1显然不可能能够赋值给int32类型,编译报错//fmt.Println(x)}


*** 第二种情况

package mainimport ("fmt"
)func main() {/*2、返回值 = 常量 + 变量要求1:和常量 + 常量的情况一样要求2:变量的类型和返回值类型必须要一致*/var x float64 = 10.9var result float64 = x + 36	//可以通过,类型一致fmt.Println(result)var y float32 = 10.0result = y + 36		//编译出错,y和返回值类型不一致fmt.Println(result)
}


*** 第三种情况

package mainimport ("fmt"
)func main() {/*3、返回值 = 变量 + 变量要求:变量的类型和返回值类型必须要一致*/var x float32 = 10.2var y float64 = 10.3fmt.Println(x + y)
}

3、算术运算符

*** 算术运算符一览表

算术运算符和c等高级语言基本上都是一致的,主要对除,取模,自增自减进行说明.

*** 详解
1、/ %

package mainimport ("fmt"
)func main() {/*除法运算特点*///如果两个整数相除,那么会结果会去掉小数部分,只保留整数部分,无论返回值整型还是浮点型var x int = 10 / 4fmt.Printf("x = %d, x type = %T\n", x, x)var y float64 = 10 / 4fmt.Printf("y = %f, y type = %T\n", y, y)//如果要保留小数位,就要用浮点数参与运算var z float64 = 10.0 / 4fmt.Printf("z = %f, z type = %T\n", z, z)
}

package mainimport ("fmt"
)func main() {/*取余运算特点取余只对整数*/// 取余公式 a % b = a - a / b * bfmt.Println("10 % 3 =", 10 % 3) // =1fmt.Println("-10 % 3 =", -10 % 3) // = -10 - (-10) / 3 * 3 = -10 - (-9) = -1fmt.Println("10 % -3 =", 10 % -3) // =1fmt.Println("-10 % -3 =", -10 % -3) // =-1
}

2、++ –

package mainimport ("fmt"
)func main() {/*自增自减只能写在变量的后面只能单独写在一行,成一条语句,不能和其他语句混合使用这些强制性规定可以除去c等高级语言中容易出现的问题*/var x int = 9x--	//等价于 x = x - 1fmt.Printf("%d\n", x)	//8x++	//等价于 x = x + 1fmt.Printf("%d\n", x)	//9
}

*** 算术运算符使用注意事项
1、对于除号 “/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。 例如: x := 19/5 ,结果是 3
2、 当对一个数取模时,可以等价 a%b=a-a/b*b , 这样我们可以看到 取模的一个本质运算。
3、 Golang 的自增自减只能当做一个独立语句使用时,不能这样使用

4、Golang 的++ 和 – 只能写在变量的后面,不能写在变量的前面,即:只有 a++ a-- 没有 ++a --a

4、关系运算符(比较运算符)

*** 基本介绍
关系运算符的结果都是 bool 型,也就是要么是 true,要么是 false
关系表达式 经常用在 if 结构的条件中或循环结构的条件中

*** 关系运算符一览图

package mainimport ("fmt"
)func main() {var x int = 90var y int = 100fmt.Println("x == y ?", x == y)  	//falsefmt.Println("x != y ?", x != y) 	//truefmt.Println("x <= y ?", x <= y) 	//truefmt.Println("x >= y ?", x >= y) 	//falsefmt.Println("x < y ?", x < y)  		//truefmt.Println("x > y ?", x > y)  		//false/*比较运算符和算术计算时一样,如果是两个变量比较,他们的类型必须完全一致如果两个都是常量,那么他们没有强制要求如果一个是变量一个是常量,那么常量的显式数值必须是和变量一致(除了浮点型时,小数点后面全是0)*/// var z int8 = 0.0// fmt.Println("x > z ?", x > z) //invalid operation: x > z (mismatched types int and int8)fmt.Println("10 > 10.2 ? ", 10 > 10.9)		// false//fmt.Println("x > 10.9 ? ", x > 10.9)		// .\go1.go:26:33: 10.9 (untyped float constant) truncated to intfmt.Println("x > 10.0 ? ", x > 10.00000) 	// true
}

5、逻辑运算符

*** 基本介绍
用于连接多个条件(一般来讲就是关系表达式),最终的结果也是一个 bool 值。



*** 注意事项和细节说明

  1. &&也叫短路与:如果第一个条件为 false,则第二个条件不会判断,最终结果为 false
  2. ||也叫短路或:如果第一个条件为 true,则第二个条件不会判断,最终结果为 true
    这种情况和其他语言是一样的。
package mainimport ("fmt"
)func test() bool {fmt.Println("Testing...")return true
}func main() {var age int = 40if age < 30 && test() {fmt.Println("yes")}if age > 30 || test() {fmt.Println("no")}}

6、赋值运算符

*** 基本介绍
赋值运算符就是将某个运算后的值,赋给指定的变量。和其他语言是一样的。

*** 赋值运算符分类

*** 特点

7、位运算符

*** 说明
位运算符是基于二进制的计算

8、其他运算符


和c语言的使用方式一样。* 在声明变量的时候是指针变量,当用 和一个指针变量配合使用 *x的时候就是取x指针变量所指向的值。

9、运算符优先级和结合律

*** 一览表

10、键盘输入

*** 步骤

  1. 导入 fmt 包
  2. 调用 fmt 包的 fmt.Scanln() 或者 fmt.Scanf()


    1、Scanln
package mainimport ("fmt"
)func main() {//录入姓名、年龄、薪水、是否通过考试//1、使用fmt.Scanlnvar name stringvar age bytevar sal float32var isPass boolfmt.Println("请输入姓名: ")fmt.Scanln(&name)fmt.Println("请输入年龄: ")fmt.Scanln(&age)fmt.Println("请输入薪水: ")fmt.Scanln(&sal)fmt.Println("请输入是否通过考试: ")fmt.Scanln(&isPass)fmt.Printf("姓名 %v\t, 年龄 %v\t, 薪水%v\t, 是否通过考试 %v\t\n", name, age, sal, isPass)}


2、Scanf

package mainimport ("fmt"
)func main() {//录入姓名、年龄、薪水、是否通过考试//2、使用fmt.Scanfvar name stringvar age bytevar sal float32var isPass boolfmt.Println("请输入你的姓名,年龄,薪水,以及是否通过考试 , 空格隔开")fmt.Scanf("%s %d %f %t", &name, &age, &sal, &isPass)fmt.Printf("姓名 %v\t, 年龄 %v\t, 薪水%v\t, 是否通过考试 %v\t\n", name, age, sal, isPass)}

11、进制


package mainimport ("fmt"
)func main() {/*右移运算符 >>:低位溢出,符号位不变,并用符号位补溢出的高位左移运算符 <<: 符号位不变,低位补 */var x int = 4result := x >> 2	//相当于x / (2的2次方)result1 := 16 >> 3  //相当于 16 / (2的3次方)fmt.Println(result)fmt.Println(result1)fmt.Println(-1 << 2)	//相当于-1 * (2的2次方)
}

Golang中的程序流程控制

1、基本介绍

流程控制主要是顺序流程,分支流程和循环流程。

2、分支语句

1. 单分支if

*** 基本语法

if 条件表达式 {执行代码}
//执行代码只有一行也要加上 {}
//可以在if中直接定义一个变量,但是不能使用var,所以只能用 := 的形式
//但是只能创建一个变量,多了会报错。
//if条件表达式不能是赋值语句

*** 测试

package mainimport ("fmt"
)func main() {//if单分支var age intfmt.Scanf("%d", &age)if age > 18 {fmt.Printf("你是成年人\n")}//golang支持在if中直接定义一个变量,用分号隔开。只能用 := 形式定义变量if salary := 18888.8; salary > 10000 {fmt.Printf("你的薪资高于平均水平\n")}
}
2. 双分支 if else

*** 基本语法

	/*1、必执行其中一条分支2、else { 不能另起一行,否则语法错误*/if 条件表达式 {执行代码} else {执行代码}

*** 测试

package mainimport ("fmt"
)func main() {//if else双分支var age intfmt.Scanf("%d", &age)/*1、必执行其中一条分支2、else { 不能另起一行,否则语法错误*/if age > 18 {fmt.Printf("你是成年人\n")} else {fmt.Println("你是未成年人")}}
package mainimport ("fmt"
)func main() {//判断是否是闰年if year := 2009; (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {fmt.Println("year is 闰年")} else {fmt.Println("year is 平年")}
}
3. 多分支 if else if…、switch

1、if else if … [else]
出现分支嵌套最多不要超过三层。

if 条件表达式1 {执行代码1} else if 条件表达式2{执行代码2}... else {执行代码}//只有一个执行入口//else 不是必须的


2、switch case
*** 基本介绍
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上到下逐一测试,直到匹配为止。
匹配项后面也不需要再加 break,当匹配项的代码执行完后,自动跳出switch。

*** 基本语法

说明:

  1. switch 的执行的流程是,先执行表达式,得到值,然后和 case 的表达式进行比较,如果相等,就匹配到,然后执行对应的 case 的语句块,然后退出 switch 控制。
  2. 如果 switch 的表达式的值没有和任何的 case 的表达式匹配成功,则执行 default 的语句块。执行后退出switch的控制。
  3. golang 的 case 后的表达式可以有多个,使用 逗号 间隔.
  4. golang 中的 case 语句块不需要写 break , 因为默认会有,即在默认情况下,当程序执行完 case 语句块后,就直接退出该 switch 控制结构。

*** switch的使用的注意事项和细节

  1. case/switch 后是一个表达式( 即:常量值、变量、一个有返回值的函数等都可以)
  2. case 后的各个表达式的值的数据类型,必须和 switch 的表达式数据类型一致。
package mainimport ("fmt"
)func main() {var x int8 = 10var y int32 = 10switch x {case y:  // invalid case y in switch on x (mismatched types int32 and int8)fmt.Println("yes")default:fmt.Println("no")}}
  1. case 后面可以带多个表达式,使用逗号间隔。比如 case 表达式 1, 表达式 2 …

  2. case 后面的表达式如果是常量值(字面量),则要求不能重复

  3. case 后面不需要带 break , 程序匹配到一个 case 后就会执行对应的代码块,然后退出 switch,如果一个都匹配不到,则执行 default

  4. default 语句不是必须的.

  5. switch 后也可以不带表达式,类似 if --else 分支

  6. switch 后也可以直接声明/定义一个变量,分号结束,不推荐使用

  7. switch 穿透-fallthrough ,如果在 case 语句块后增加 fallthrough ,则会继续执行下一个 case(即使case指向的表达式是不符合的),也叫 switch 穿透.

  8. Type Switch:switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际指向的变量类型 【还没有学 interface]

4. if和switch比较

总结了什么情况下使用 switch ,什么情况下使用 if

  1. 如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用 swtich语句,简洁高效。
  2. 其他情况:对区间判断和结果为 bool 类型的判断,使用 if,if 的使用范围更广。

3、 循环语句

***** 没有c中的while和do...while循环,只有for循环

for循环

*** 基本语法

package mainimport ("fmt"
)func main() {for i := 1; i < 10; i++ {fmt.Println(i) // 输出1 - 9}}

*** 使用细节和注意事项

  1. 循环条件是返回一个布尔值的表达式
  2. for 循环的第二种使用方式
package mainimport ("fmt"
)func main() {var i int = 1for i < 10 {fmt.Println(i)i++}}
  1. for 循环的第三种使用方式
package mainimport ("fmt"
)func main() {var i = 1for {if(i < 10){fmt.Println(i)  // 输出1 - 9} else {break}i++}
}
  1. Golang 提供 for-range 的方式,可以方便遍历字符串和数组
    传统遍历字符串方式:
package mainimport ("fmt"
)func main() {var str = "HELLO WORLD!!"//len是10几个内置函数之一for i := 0; i < len(str); i++ {fmt.Printf("%c", str[i])}fmt.Println()
}

使用for-range方式

package mainimport ("fmt"
)func main() {var str = "HELLO WORLD!!你好"for index, val := range str {	//index和val不需要是已定义好的变量fmt.Printf("index = %d, val = %c \n", index, val)}}

两种遍历方式的细节讨论
如果我们的字符串含有中文,那么传统的遍历字符串方式,就是错误,会出现乱码。原因是传统的对字符串的遍历是按照字节来遍历,而一个汉字在 utf8 编码是对应 3 个字节。(for-range遍历方式是按照字符方式遍历。因此如果有字符串有中文,也是 ok的)

如何解决—> 需要将 str 转成 [ ]rune 切片.

4、跳转语句

1. break语句

*** 基本介绍
用于中断循环语句和跳出switch。

*** 注意事项和使用细节
break语句在多层嵌套的循环语句中时,默认跳出最近的循环;其实可以通过指定标签来跳出指定的循环

2. continue语句

*** 基本介绍
continue语句默认用于结束本次循环,继续执行下一次循环。
continue语句出现在多层嵌套的循环语句中时,可以通过标签指明要跳过的哪一层循环,这个和前面的break使用规则一样。

4. 跳转控制语句goto
  1. Go语言的goto语句可以无条件地转移到程序中指定的行
  2. goto语句通常与条件语句配合使用。可用来实现条件转移,跳出循环体等功能。
  3. 在Go程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难。
5. 跳转控制语句return

*** 基本介绍
return使用在方法或者函数中,表示跳出所在的方法或函数。

  1. 如果return是在普通的函数,则表示跳出该函数,即不再执行函数中 return后面代码,也可以理解成终止函数。
  2. 如果return是在main函数,表示终止main函数,也就是说终止程序。
6. 总结

上面几种跳转语句和c语言基本都是一致的,也就是break和continue添加了标签的功能。

更多推荐

1、Go核心编程(基础部分)

本文发布于:2024-03-07 04:15:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1716823.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:核心   基础

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!