Go语言学习笔记—golang基础语法

视频来源:B站《golang入门到项目实战 [2022最新Go语言教程,没有废话,纯干货!]》

文章为自己整理的学习笔记,侵权即删,谢谢支持!

文章目录

  • golang基础语法
      • 一、golang标识符、关键字、命名规范
        • 1.1 标识符概念
        • 1.2 标识符命名规则
        • 1.3 关键字
        • 1.4 命名规范
          • 1.4.1包命名
          • 1.4.2 文件命名
          • 1.4.3 结构体命名
          • 1.4.4 接口命名
          • 1.4.5 变量命名
          • 1.4.6 常量命名
          • 1.4.7 错误处理
          • 1.4.8 单元测试
      • 二 golang变量
        • 2.1 声明变量
        • 2.2 变量的初始化
          • 2.2.1 语法
          • 2.2.2 初始化多个变量
        • 2.3 短变量声明
        • 2.4 匿名变量
      • 三 golang常量
        • 3.1 定义常量
        • 3.2 特殊关键字`iota`
      • 四 golang数据类型
        • 4.1 简介
        • 4.2 布尔类型
        • 4.3 数字类型
          • 4.3.1 整型
          • 4.3.2 以二进制、八进制或十六进制浮点数的格式定义数字
          • 4.3.3 浮点型
          • 4.3.4 复数
        • 4.4 字符串类型
          • 4.4.1 golang字符串字面量
          • 4.4.2 golang字符串拼接
          • 4.4.3 golang字符串转义字符
          • 4.4.4 golang字符串切片操作
          • 4.4.5 golang字符串常用方法
      • 五 golang格式化输出
        • 5.1 普通占位符
        • 5.2 布尔占位符
        • 5.3 整数占位符
        • 5.4 浮点数和复数的组成部分(实部与虚部)
        • 5.5 字符串与字节切片
        • 5.6 指针
      • 六 基本数据类型的相互转换
        • 6.1 数据类型的基本默认值
        • 6.2 基本数据类型相互转换的基本语法
        • 6.3 基本数据类型相互转换的注意事项
        • 6.4 基本类型转字符串类型
        • 6.5 字符串类型转基本数据类型
      • 七、golang运算符
        • 7.1 算术运算符
        • 7.2 关系运算符
        • 7.3 逻辑运算符
        • 7.4 位运算符
        • 7.5 赋值运算符
        • 7.6 其他运算符
        • 7.7 运算符的优先级

golang基础语法

一、golang标识符、关键字、命名规范

1.1 标识符概念

  1. Golang 对各种变量、常量、方法、函数、结构体、数组、切片、接口命名时使用的字符序列称为标识符
  2. 凡是自己可以起名字的地方都叫标识符

1.2 标识符命名规则

  1. 由 26 个英文字母大小写、0-9 和 _ 组成

  2. 数字不可以开头。

  3. Golang 中严格区分大小写。

  4. 标识符不能包含空格。

  5. 下划线_本身在 Go 中是一个特殊的标识符,称为空标识符。可以代表任何其它的标识符,但是它对应的值会被忽略(比如:忽略某个返回值)。所以仅能被作为占位符使用,不能作为标识符使用

  6. 不能以系统保留关键字作为标识符(一共有 25 个),比如 breakif 等等…

举例:

正确的命名

package main

import "fmt"

func main(){
    var name string
    var age int
    var _sys int
}

错误的命名

package main

import "fmt"

func main(){
    var 1name string
    var &age int
    var !abc
}

hello // ok
hello12 //ok
1hello // error ,不能以数字开头
h-b // error ,不能使用 -
x h // error, 不能含有空格

h_4 // ok
_ab // ok
int // ok , 我们要求大家不要这样使用
float32 // ok , 我们要求大家不要这样使用
_ // error
Abc // ok

1.3 关键字

在Go中,为了简化代码编译过程中对代码的解析,其定义保留关键字只有25个,如下

Go语言学习笔记—golang基础语法_第1张图片

除了以上介绍的这些关键字,Go语言还有36个预定义标识符,其中包含了基本类型的名称和一些基本的内置函数,如下:

Go语言学习笔记—golang基础语法_第2张图片

1.4 命名规范

命名规范设计变量、常量、全局函数、结构、方法等等的命名。

Go语言从语法层面进行了以下限定:任何需要对外暴露的名字必须以大写字母开头,不需要对外暴露的则以小写字母开头。

当一个命名以一个大写字母开头,如GetUserName,那么使用这种形式的标识符的对象就可以被外部包的代码使用(客户端程序需要先导入这个包),这被称为导出(如面向对象语言中的public);命名如果以小写字母开头,则对包外是不可兼得,但是他们在整个包的内部是可见的并且可用的(如面向对象语言中的private)

1.4.1包命名

保持package的名字和目录保持一致,尽量采用有意义的包名,简短、有意义且尽量和标准库不要冲突。包命应该为小写单词,不要使用下划线或者混合大小写。

package psych
package service
1.4.2 文件命名

尽量采用有意义且简短的文件名,应为小写单词,使用下划线分隔各个单词

customer_dao.go
1.4.3 结构体命名

采用驼峰命名法,首字母根据访问控制大小写

struct 声明和初始化格式采用多行,例:

type CustomerOrder struct{
    Name string
    Address string
}
order := CustomerOder{"psych","四川成都"}
1.4.4 接口命名

命名规则基本上与上面结构体类似

单个函数的结构名以“er”作为后缀,例如ReaderWriter

type Reader interface{
    Read(p []byte)(n int,err error)
}
1.4.5 变量命名

和结构体类似,一般遵循驼峰命名法,首字母根据访问控制大小写,但遇到特有名词时,需要遵循以下规则:

如果变量为私有,且特有名词为首个单词,则使用小写,如 appService;若变量为bool类型,则名称应以has、is、can或allow开头

var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
1.4.6 常量命名

常量需使用全部大写字母组成,并使用下划线分词

const APP_URL = "https://www.baidu.com"

如果是枚举类型的常量,需要先创建对应类型

type Scheme string

const{
    HTTP Scheme = "http"
    HTTPS Scheme = "https"
}
1.4.7 错误处理

错误处理的原则是不能丢弃任何有返回err的调用,不要使用_丢弃,必须全部处理。接收到错误,要么返回err,或者使用log记录下来尽早return;一旦有错误发生,马上返回,尽量不要使用panic,除非你知道你在做什么,错误描述如果是英文必须为小写,不需要标点结束,采用独立的错误流进行处理

Go语言学习笔记—golang基础语法_第3张图片

1.4.8 单元测试

单元测试文件命名规则为example_test.go 测试用例的函数名称必须以Test开头,例如:TestExample每个重要的函数都要首先编写测试用例,测试用例和正规代码一起提交方便进行回归测试

二 golang变量

变量相当于内存中一个数据存储空间的表示,不同的变量保存的数据类型可能会不一样。你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,同样的道理,通过变量名可以访问到变量(值)。

2.1 声明变量

Go语言中的变量需要声明后才能使用,同一作用域内不支持重复声明,并且Go语言的变量声明后必须使用。

语法

var identifier type

var:声明变量关键字

identifier:变量名称

type:变量类型

例如:

package main

import "fmt"

func main(){
    var name string
    var age int
    var married bool
}

批量声明

使用一个var关键字,把一些变量写在一个括号()

package main

import "fmt"

func main(){
    var (
    	name string
    	age int
    	married bool
    )
}

2.2 变量的初始化

Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化,每个变量会被初始化成其他类型的默认值,例如:整型和浮点型变量的默认值为0;字符串变量的默认值为空字符串""。bool类型变量默认为false;切片、函数、指针变量的默认值为nil

2.2.1 语法
var 变量名 类型 = 表达式

例如:

package main

import "fmt"

func main(){
    var name string = "Psych"
    var age int = 18
    var married bool = False
}
2.2.2 初始化多个变量

可一次性初始化多个变量,中间用逗号隔开

package main

import "fmt"

func main(){
 	var name, age, married = "Psych", 18, False   
}

2.3 短变量声明

在函数内部可以用:=运算符对变量进行声明和初始化

package main

import "fmt"

func main(){
    name := "Psych"
    age := 18
    married := False
}

注:此方法只适用于函数内部,函数外部不可使用

2.4 匿名变量

若我们接收到多个变量,有一些变量使用不到,则可使用_表示变量名称,这种变量即为匿名变量

package main

import "fmt"

func getNameAndAge(string, int){
    return "Psych", 18
}

func main(){
    name, _ := getNameAndAge()
    fmt.Printf("name: %v\n", name)
}

三 golang常量

常量即为程序在编译阶段就已经确定的值,而程序运行时则无法改变该值,即一旦定义则无法修改。

在Go中常量可以为数值类型、布尔类型或者字符串类型等。

3.1 定义常量

语法:

const constantName [type] = value

const:定义常量的关键字

constantName:常量名称

type:常量类型(可省略)

value:常量的值

举例:

package main

import "fmt"

func main(){
	//单常量声明:
    const PI float64 = 3.14
    const PI2 = 3.1415 //可省略类型
    //多常量声明:
    const (
    	W = 100
    	H = 100//多重赋值
    const i, j = 1, 2
    const a, b, c = 3, 4, "foo"
}

注:const 同时声明多个常量时,若省略了值则表示和和上面一行值相同

package main

import "fmt"

func main(){
    const (
    	A = 100
    	B 
    	C
    )
    
    fmt.Printf("A: %v\n", A)
    fmt.Printf("B: %v\n", B)
    fmt.Printf("C: %v\n", C)

}

其运行结果为:

A:100
B:100
C:100

3.2 特殊关键字iota

iota可被认为是一个可被编译修改的常量,其默认值为0,每次调用一次则加1,遇到const关键字时被重置为0

package main

import "fmt"

func main(){
    const (
    	A = iota //0
    	B = iota //1(i++)
    	C = iota //2
    )
    
    fmt.Printf("A: %v\n", A)
    fmt.Printf("B: %v\n", B)
    fmt.Printf("C: %v\n", C)

}

运行结果:

A:0
B:1
C:2

使用_可跳过某些值

package main

import "fmt"

func main(){
    const (
    	A = iota //0
    	_ 		 //1
    	C = iota //2 
    )
    
    fmt.Printf("A: %v\n", A)
    fmt.Printf("C: %v\n", C)

}

运行结果为

A:0
C:2

iota可声明中间插队

package main

import "fmt"

func main(){
    const (
    	A = iota //0
    	B = 100
    	C = iota //2
    )
    
    fmt.Printf("A: %v\n", A)
    fmt.Printf("B: %v\n", B)
    fmt.Printf("C: %v\n", C)

}

运行结果为:

A:0
B:100
C:2

四 golang数据类型

4.1 简介

在Go语言中,数据类型用于声明函数和变量。每一种数据都定义了明确的数据类型,在内重中分配了不同大小的内存空间。

Go语言学习笔记—golang基础语法_第4张图片

Go也有基于架构的类型,例如:int、uint、uintptr

Go语言学习笔记—golang基础语法_第5张图片

浮点型:

Go语言学习笔记—golang基础语法_第6张图片

其他数字类型:

Go语言学习笔记—golang基础语法_第7张图片

4.2 布尔类型

布尔类型也叫 bool 类型,bool 类型数据只允许取值 truefalse。bool 类型的数据占 1 个字节。布尔类型适于逻辑运算,一般用于程序流程控制中的条件控制语句,或者循环控制语句

package main

import "fmt"

func main(){
    var b1 bool = true
    var b2 bool = false
    
    var b3 = true //也可省略类型
    var b4 = false
    
    b5 := true //短变量形式
    b6 := false
    
    fmt.Printf("b1: %v\n", b1)
	fmt.Printf("b2: %v\n", b2)
    fmt.Printf("b3: %v\n", b3)
    fmt.Printf("b4: %v\n", b4)
    fmt.Printf("b5: %v\n", b5)
    fmt.Printf("b6: %v\n", b6)

}

运行结果为:

b1:true
b2:false
b3:true
b4:false
b5:true
b6:false

用于if条件控制语句中

package main

import "fmt"

func main(){
    age := 18
    adult := age >= 18 // 此处adult数据类型为bool型
    fmt.Printf("adult: %v\n",adult)
    
    if adult {
        fmt.Printf("成年人")
    }else {
        fmt.Printf("未成年")
    }
}

运行结果为:

adult: true
成年人

用于循环控制语句中

package main

import "fmt"

func main(){
    count := 10
    for i := 0;i < count; i++ { // 此处i
        fmt.Printf("i=%v\n", i)
    }
}

运行结果为:

i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9

用于逻辑表达式中

package main

import "fmt"

func main(){
    age := 18
    gender := "男"
    
    if age >= 18 && gender == "男" {
        fmt.Printf("是成年男性")
    }
    }
}

注:不能使用0或者非0表示真假

package main

import "fmt"

func main(){
    i := 1
    if i {
        // 此时编译出错
    }
}

4.3 数字类型

Go语言支持整型和浮点型数字,并原生支持复数,其中位的运算采用补码。

Go语言中也有基于架构的类型,如intuintuintptr。这些类型的长度都是根据运行程序所在的操作系统类型所决定的:

  • intuint在32位操作系统上,它们均使用32位(即4个字节);在64位操作系统上,它们均使用64位(即8个字节)

  • uintptr的长度被设定为足够存放一个指针即可

注:Go语言中没有float类型(只有float32float64),也没有double类型。

与操作系统架构无关的类型都有固定的大小:

4.3.1 整型

① 有符号整数:

类型 有无符号 表示范围
int8 -128 ~ 127
int16 -2^15 ~ 2^15 - 1
int32 -2^31 ~ 2^31 - 1
int64 -2^63 ~ 2^63 - 1

② 无符号整数:

类型 有无符号 表示范围
uint8 0 ~ 255
uint16 0 ~ 2^16 - 1
uint32 0 ~ 2^32 - 1
uint64 0 ~ 2^64 - 1
4.3.2 以二进制、八进制或十六进制浮点数的格式定义数字
package main

import "fmt"

func main(){
    // 十进制
    var a int = 10
    fmt.Printf("%d \n", a)
    fmt.Printf("%b \n", a) //占位符%b表示二进制

    // 八进制(以0开头)
    var b int = 077
    fmt.Printf("%o \n", b)
    
    // 十六进制(以0x开头)
    var c int = 0xff
    fmt.Printf("%x \n", c)
    fmt.Printf("%X \n", c)

}

运行结果:

10
1010
77
ff
FF
4.3.3 浮点型

Go语言支持两种浮点型:float32float64。这两种浮点型都遵循IEEE 754标准。

类型 表示范围
float32 -3.403E38 ~ 3.408E38
float64 -1.798E308 ~ 1.798E308

注:整型的零值为0,浮点型的零值为0.0

float32可以使用一个常量定义:math.MaxFloat32

float64可以使用一个常量定义:math.MaxFloat64

打印浮点数时可使用fmt包配合动词%f,例如:

package main

import (
	"fmt"
    "math"
)

func main(){
    fmt.Printf("%f \n", math.Pi)
    fmt.Printf("%.2f \n", math.Pi) // %.2f值取小数点后两位
}

运行结果为:

3.141593
3.14
4.3.4 复数

complex64complex128

var c1 complex64
c1 = 1 + 2i
var c2 complex128
c2 = 2 + 3i
fmt.Printf(c1)
fmt.Printf(c2)

复数有实部和虚部,complex64 的实部和虚部为32位 complex128 的实部和虚部为64位

4.4 字符串类型

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

4.4.1 golang字符串字面量

在Go语言中,字符串字面量使用双引号""或者反引号``来创建。

双引号"": 用于创建可解析的字符串,会识别转义字符,但不用来引用多行。应用广泛。
反引号``:用于创建原生的字符串,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果,但不支持转义。多用于书写多行消息、HTML以及正则表达式。

package main

import "fmt"

func main(){
    var str1 string = "hello world"
    var html string = `
    	
    		hello Go
    	
    `
    
    fmt.Printf("str1: %v\n", str1)
    fmt.Printf("html: %v\n", html) 
}

运行结果

str1: hello world
html:

	hello Go

4.4.2 golang字符串拼接

① 使用加号拼接

Go语言支持+级联操作和+=追加操作

package main

import "fmt"

func main(){
    str1 := "Psych"
    str2 := "永远18岁"
    msg := str1 + str2
    
    fmt.Printf("msg: %v\n", msg) 
}

运行结果:

msg: Psych永远18岁

注:由于golang里的字符串都是不变的,每次运算都会产生一个新的字符串,所以会产生很多临时的无用的字符串,因此会给pc带来额外的负担导致性能变差

② 使用fmt.Sprintf()函数

package main

import "fmt"

func main(){
    str1 := "Psych"
    str2 := "永远18岁"
    msg := fmt.Sprint("%s,%s", str1, str2)
    
    fmt.Printf("msg: %v\n", msg) 
}

运行结果:

msg: Psych,永远18岁

注:内部使用[]byte实现,不想直接运算符这种会产生很多临时的字符串,但是内部逻辑很复杂,有很多额外的判断,还用到了interface,因此性能也不是很好。

③ 使用strings.Join()

package main

import "fmt"

func main(){
    str1 := "Psych"
    str2 := "永远18岁"
    msg := strings.Join([]string{str1, str2}, ",")
    
    fmt.Printf("msg: %v\n", msg) 
}

运行结果:

msg: Psych,永远18岁

注:Join会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,将一个一个字符串依次填入,在已有一个数组的情况下,此方法效率会很高,但是若未存在此数组,则构造这个数据的代价也不小。

④ 使用buffer.WriteString()

package main

import "fmt"

func main(){
    var buffer bytes.Buffer
    buffer.WriteString("Psych")
    buffer.WriteString(",")
    buffer.WriteString("永远18岁")

    fmt.Printf("buffer.String(): %v\n", buffer.String()) 
}

运行结果:

buffer.String(): Psych,永远18岁

注:此方法较为理想,可当成可变字符使用,对内存的增长也有优化,若能预估字符串的长度,还可使用buffer.Grow()接口来设置capacity

4.4.3 golang字符串转义字符

Go语言学习笔记—golang基础语法_第8张图片

应用举例:

package main

import "fmt"

func main() {
	s1 := "hello world"
	fmt.Printf("s1: %v\n", s1)

	s2 := "hello\nworld" // 制表符四个空格
	fmt.Printf("s2: %v\n", s2)

	s3 := "hello\tworld"
	fmt.Printf("s3: %v\n", s3)

	s4 := "c:\\program files\\a"
	fmt.Printf("s4: %v\n", s4)

}

运行结果

s1: hello world
s2: hello
world
s3: hello	world
s4: c:\program files\a
4.4.4 golang字符串切片操作
package main

import "fmt"

func main() {
	s := "hello world"
	n := 3
	m := 5

	fmt.Printf("s: %v\n", s)

	fmt.Printf("s[n]: %v\n", s[n])     // 获取字符串索引位置为 n 的原始字节
	fmt.Printf("s[n:m]: %v\n", s[n:m]) // 截取字符串索引位置为 n 到 m-1 的字符串
	fmt.Printf("s[n:]: %v\n", s[n:])   // 截取字符串索引位置为 n 到 len(s)-1 的字符串
	fmt.Printf("s[:m]: %v\n", s[:m])   // 截取字符串索引位置为 0 到 m-1 的字符串

}


运行结果:

s: hello world
s[n]: 108
s[n:m]: lo
s[n:]: lo world
s[:m]: hello
4.4.5 golang字符串常用方法

Go语言学习笔记—golang基础语法_第9张图片

应用举例:

package main

import (
	"fmt"
	"strings"
)

func main() {
	s := "Hello World"

	fmt.Printf("s: %v\n", s)
	fmt.Printf("len(s): %v\n", len(s))
	fmt.Printf("strings.Split(s, \"\"): %v\n", strings.Split(s, ""))                 // 得到的是一个数组
	fmt.Printf("strings.Contains(s, \"hello\"): %v\n", strings.Contains(s, "hello")) // 是否包含hello
	fmt.Printf("strings.ToLower(s): %v\n", strings.ToLower(s))                       // 全部小写
	fmt.Printf("strings.ToUpper(s): %v\n", strings.ToUpper(s))                       // 全部大写

	fmt.Printf("strings.HasPrefix(\"Hello\"): %v\n", strings.HasPrefix(s, "Hello"))    // 判断前缀
	fmt.Printf("strings.HasSuffix(s, \"world\"): %v\n", strings.HasSuffix(s, "world")) // 判断后缀(区分大小写)

	fmt.Printf("strings.Index(s, \"l\"): %v\n", strings.Index(s, "l"))         // 第一次出现l的索引位置
	fmt.Printf("strings.LastIndex(s, \"l\"): %v\n", strings.LastIndex(s, "l")) // 最后一次出现l的索引位置

}

运行结果:

s: Hello World
len(s): 11
strings.Split(s, ""): [H e l l o   W o r l d]
strings.Contains(s, "hello"): false
strings.ToLower(s): hello world
strings.ToUpper(s): HELLO WORLD
strings.HasPrefix("Hello"): true
strings.HasSuffix(s, "world"): false
strings.Index(s, "l"): 2
strings.LastIndex(s, "l"): 9

五 golang格式化输出

5.1 普通占位符

说明:

占位符 说明
%v 相应值的默认格式
%+v 打印结构体时,添加字段名
%#v 相应值的Go语言语法表示
%T 相应值的类型的Go语言语法表示
%% 字面上的百分号,并非值的占位符

注:下面实例使用到的结构体为:

type Website struct {
    Name string
}
 
// 定义结构体变量
var site = Website{Name: "duoke360"}

应用举例:

package main

import (
	"fmt"
)

type WebSite struct {
	Name string
}

func main() {
	site := WebSite{Name: "duoke360"}
	fmt.Printf("site: %v\n", site)
	fmt.Printf("site: %#v\n", site)
	fmt.Printf("site: %T\n", site)
	a := 100
	fmt.Printf("a: %T\n", a)
	fmt.Println("%%")
}

运行结果:

site: {duoke360}
site: main.WebSite{Name:"duoke360"}
site: main.WebSite
a: int
%%

5.2 布尔占位符

占位符 说明
%t 单词true或false

应用举例:

package main

import (
	"fmt"
)

type WebSite struct {
	Name string
}

func main() {
	b := true
	fmt.Printf("b: %t\n", b)
}

运行结果:

b: true

5.3 整数占位符

占位符 说明
%b 二进制表示
%c 相应unicode码点所表示的字符
%d 十进制表示
%o 八进制表示
%q 单引号围绕的字符字面值,由Go语言安全地转义
%x 十六进制表示,字母形式为小写 a-f
%X 十六进制表示,字母形式为大写 A-F
%U Unicode格式:U+1234,等同于 “U+%04X”

应用举例:

package main

import (
	"fmt"
)

type WebSite struct {
	Name string
}

func main() {
	i := 8
	fmt.Printf("i: %v\n", i)
	fmt.Printf("i: %b\n", i)
	i = 96
	fmt.Printf("i: %c\n", i)
	fmt.Printf("i: %x\n", 100)
	fmt.Printf("i: %x\n", 1234)
	fmt.Printf("i: %X\n", 1234)
}

运行结果:

i: 8
i: 1000
i: `
i: 64
i: 4d2
i: 4D2

5.4 浮点数和复数的组成部分(实部与虚部)

占位符 说明
%b 无小数部分的,指数为二的幂的科学计数法,与strconv.FormatFloat'b' 转换格式一致。例如 -123456p-78
%e 科学计数法,例如 -1234.456e+78
%E 科学计数法,例如 -1234.456E+78
%f 有小数点而无指数,例如 123.456
%g 根据情况选择 %e%f 以产生更紧凑的(无末尾的0)输出
%G 根据情况选择 %E%f 以产生更紧凑的(无末尾的0)输出

5.5 字符串与字节切片

占位符 说明
%s 输出字符串表示(string类型或[]byte)
%q 双引号围绕的字符串,由Go语法安全地转义
%x 十六进制,小写字母,每字节两个字符
%X 十六进制,大写字母,每字节两个字符

5.6 指针

占位符 说明
%p 十六进制表示,前缀 0x

应用举例:

package main

import (
	"fmt"
)

type WebSite struct {
	Name string
}

func main() {
	x := 100
	p := &x
	fmt.Printf("i: %p\n", p)
}

运行结果:

i: 0xc000014098

六 基本数据类型的相互转换

6.1 数据类型的基本默认值

在 go 中,数据类型都有一个默认值,当程序员没有赋值时,就会保留默认值,在 Go 中,默认值
又叫零值。

数据类型 默认值
整型 0
浮点型 0
字符串 “”
布尔类型 false

案例:

package main

import "fmt"

func main() {
	var a int
	var b float32
	var c float64
	var d bool
	var name string

	fmt.Printf("a: %v\n", a)
	fmt.Printf("b: %v\n", b)
	fmt.Printf("c: %v\n", c)
	fmt.Printf("d: %v\n", d)
	fmt.Printf("name: %v\n", name)
}

运行结果:

a: 0
b: 0
c: 0
d: false
name: 

6.2 基本数据类型相互转换的基本语法

Go 在不同类型的变量之间赋值时需要显式转换。也就是说 Golang 中数据类型不能自动转换。

表达式为 T(v)即将值v转换为类型T,其中T: 就是数据类型,比如 int32,int64,float32 等;v: 就是需要转换的变量

案例:

package main

import "fmt"

func main() {
	var i int32 = 100
    // 将i =》 float
	var n1 float32 = float32(i)
	var n2 int16 = int16(i)
	var n3 int8 = int8(i)

	fmt.Printf("i: %v\n", i)
	fmt.Printf("n1: %v\n", n1)
	fmt.Printf("n2: %v\n", n2)
	fmt.Printf("n3: %v\n", n3)
}

6.3 基本数据类型相互转换的注意事项

① Go 中,数据类型的转换可以是从 表示范围小–>表示范围大,也可以 范围大—>范围小

② 被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化!例如:

package main

import "fmt"

func main() {
	var i int32 = 100
	var n1 float32 = float32(i)

	fmt.Printf("i: %v\n", i)
	fmt.Printf("n1: %v\n", n1)

	fmt.Printf("i 的数据类型是: %T\n", i)
}
i: 100
n1: 100
i 的数据类型是: int32

③ 在转换中,比如将 int64 转成 int8,编译时不会报错,只是转换的结果是按溢出处理,和我们希望的结果不一样。 因此在转换时,需要考虑范围.

package main

import "fmt"

func main() {
	var n1 int64 = 999999
	var n2 int8 = int8(n1)

	fmt.Printf("n2: %v\n", n2)

}
n2: 63

6.4 基本类型转字符串类型

① 使用fmt.Sprintf

语法:fmt.Sprintf("%参数", 表达式)

根据参数生成格式化的字符串并返回该字符串

应用实例:

package main

import "fmt"

func main() {
	var n1 int = 99
	var n2 float64 = 23.456
	var n3 bool = true
	var n4 byte = 'h'

	var str string

	str = fmt.Sprintf("%d", n1)
	fmt.Printf("str的数据类型是%T str=%q\n", str, str)

	str = fmt.Sprintf("%f", n2)
	fmt.Printf("str的数据类型是%T str=%q\n", str, str)

	str = fmt.Sprintf("%t", n3)
	fmt.Printf("str的数据类型是%T str=%q\n", str, str)

	str = fmt.Sprintf("%c", n4)
	fmt.Printf("str的数据类型是%T str=%q\n", str, str)

}

运行结果:

str的数据类型是string str="99"
str的数据类型是string str="23.456000"
str的数据类型是string str="true"
str的数据类型是string str="h"

② 使用 strconv 包的函数

在这里插入图片描述

应用实例:

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var n1 int = 99
	var n2 float64 = 23.456
	var n3 bool = true

	var str string

	str = strconv.FormatInt(int64(n1), 10)
	fmt.Printf("str的数据类型是: %T str=%q\n", str, str)

	str = strconv.FormatFloat(n2, 'f', 10, 64)
	// 其中'f'格式10表示小数位保留10位,64表示这个小数是float64
	fmt.Printf("str的数据类型是: %T str=%q\n", str, str)

	str = strconv.FormatBool(n3)
	fmt.Printf("str的数据类型是: %T str=%q\n", str, str)

}

运行结果:

str的数据类型是: string str="99"
str的数据类型是: string str="23.4560000000"
str的数据类型是: string str="true"

6.5 字符串类型转基本数据类型

使用strconv包的函数:

在这里插入图片描述

应用举例:

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var str1 string = "true"
	var b bool

	b, _ = strconv.ParseBool(str1)
	// strconv.ParseBool(str)函数会返回两个值(value bool , err error)
	// 因此只想获取value bool 而不想获取err,则可使用_忽略
	fmt.Printf("b的数据类型是 %T b=%v\n", b, b)

	var str2 string = "1234590"
	var n1 int64
	var n2 int
	n1, _ = strconv.ParseInt(str2, 10, 64)
	n2 = int(n1)
	fmt.Printf("n1的数据类型是%T n1=%v\n", n1, n1)
	fmt.Printf("n2的数据类型是%T n2=%v\n", n2, n2)

	var str3 string = "123.456"
	var f1 float64
	f1, _ = strconv.ParseFloat(str3, 64)
	fmt.Printf("f1的数据类型是%T f1=%v\n", f1, f1)

}

运行结果:

b的数据类型是 bool b=true
n1的数据类型是int64 n1=1234590
n2的数据类型是int n2=1234590
f1的数据类型是float64 f1=123.456

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

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var str1 string = "hello"
	var n int64 = 11

	n, _ = strconv.ParseInt(str1, 10, 64)
	fmt.Printf("n的数据类型是 %T n=%v\n", n, n)
}
// n的数据类型是 int64 n=0

七、golang运算符

Go 语言内置的运算符有:

  1. 算术运算符
  2. 关系运算符
  3. 逻辑运算符
  4. 位运算符
  5. 赋值运算符

7.1 算术运算符

运算符 描述
+ 相加
- 相减
* 相乘
/ 相除
% 求余

注意: ++(自增)和 --(自减)在Go语言中是单独的语句,并不是运算符,因此不能这样使用:

Go语言学习笔记—golang基础语法_第10张图片

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

应用举例:

package main
 
import "fmt"
 
func main() {
    a := 100
    b := 10
 
    fmt.Printf("(a + b): %v\n", (a + b))
    fmt.Printf("(a - b): %v\n", (a - b))
    fmt.Printf("(a * b): %v\n", (a * b))
    fmt.Printf("(a / b): %v\n", (a / b))
    fmt.Printf("(a %% b): %v\n", (a % b))
 
    a++
    fmt.Printf("a: %v\n", a)
    b--
    fmt.Printf("b: %v\n", b)
}

运行结果:

(a + b): 110
(a - b): 90
(a * b): 1000
(a / b): 10
(a % b): 0
a: 101
b: 9

7.2 关系运算符

运算符 描述
== 检查两个值是否相等,如果相等返回 True 否则返回 False。
!= 检查两个值是否不相等,如果不相等返回 True 否则返回 False。
> 检查左边值是否大于右边值,如果是返回 True 否则返回 False。
>= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
< 检查左边值是否小于右边值,如果是返回 True 否则返回 False。
<= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

应用举例:

package main
 
import "fmt"
 
func main() {
    a := 1
    b := 2
 
    fmt.Printf("(a > b): %v\n", (a > b))
    fmt.Printf("(a < b): %v\n", (a < b))
    fmt.Printf("(a >= b): %v\n", (a >= b))
    fmt.Printf("(a <= b): %v\n", (a <= b))
    fmt.Printf("(a == b): %v\n", (a == b))
    fmt.Printf("(a != b): %v\n", (a != b))
}

运行结果:

(a > b): false
(a < b): true
(a >= b): false
(a <= b): true
(a == b): false
(a != b): true

7.3 逻辑运算符

运算符 描述
&& 逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。
|| 逻辑 OR 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False。
! 逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True。

应用举例:

package main
 
import "fmt"
 
func main() {
    a := true
    b := false
 
    fmt.Printf("(a && b): %v\n", (a && b))
    fmt.Printf("(a || b): %v\n", (a || b))
    fmt.Printf("(!a): %v\n", (!a))
    fmt.Printf("(!b): %v\n", (!b))
}

运行结果:

(a && b): false
(a || b): true
(!a): false
(!b): true

7.4 位运算符

位运算符对整数在内存中的二进制位进行操作。

运算符 描述
& 参与运算的两数各对应的二进位相与。 (两位均为1才为1)
| 参与运算的两数各对应的二进位相或。 (两位有一个为1就为1)
^ 参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1)
<< 左移n位就是乘以2的n次方。 “a<
>> 右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。

应用举例:

package main
 
import "fmt"
 
func main() {
    a := 4 // 二进制 100
    fmt.Printf("a: %b\n", a)
    b := 8 // 二进制 1000
    fmt.Printf("b: %b\n", b)
 
    fmt.Printf("(a & b): %v, %b \n", (a & b), (a & b))
    fmt.Printf("(a | b): %v, %b\n", (a | b), (a | b))
    fmt.Printf("(a ^ b): %v, %b\n", (a ^ b), (a ^ b))
    fmt.Printf("(a << 2): %v, %b\n", (a << 2), (a << 2))
    fmt.Printf("(b >> 2): %v, %b\n", (b >> 2), (b >> 2))
}

运行结果:

a: 100
b: 1000
(a & b): 0, 0 
(a | b): 12, 1100
(a ^ b): 12, 1100
(a << 2): 16, 10000
(b >> 2): 2, 10

7.5 赋值运算符

运算符 描述
= 简单的赋值运算符,将一个表达式的值赋给一个左值
+= 相加后再赋值
-= 相减后再赋值
*= 相乘后再赋值
/= 相除后再赋值
%= 求余后再赋值
<<= 按位左移后赋值
>>= 按位右移后赋值
&= 按位与后赋值
|= 按位或后赋值
^= 按位异或后赋值

应用举例:

package main
 
import "fmt"
 
func main() {
    var a int
    a = 100
    fmt.Printf("a: %v\n", a)
    a += 1 // a = a + 1
    fmt.Printf("a: %v\n", a)
    a -= 1 // a = a -1
    fmt.Printf("a: %v\n", a)
    a *= 2 // a = a * 2
    fmt.Printf("a: %v\n", a)
    a /= 2 // a = a / 2
    fmt.Printf("a: %v\n", a)
}

运行结果:

a: 100
a: 101
a: 100
a: 200
a: 100

7.6 其他运算符

运算符 描述
& 返回变量存储地址
* 指针变量

应用举例:

package main

import (
	"fmt"
)

func main() {
	a := 100
	fmt.Println("a的地址为: ", &a)

	var ptr *int = &a
	fmt.Println("ptr指向的值是: ", *ptr)
}

运行结果:

a的地址为:  0xc000014098
ptr指向的值是:  100

7.7 运算符的优先级

Go语言学习笔记—golang基础语法_第11张图片

你可能感兴趣的:(Go语言基础学习笔记,golang,学习)