Go语言--基础语法笔记
###
换了工作,好久没有添加新文章了,本来是想更新到github上的,想想还是在博客里放着,感觉以前的文章都没有很仔细,都只是问题处理的记录,
以后想新加一些整理的笔记也好
###
主要内容
2.1变量
2.2数据类型
2.3数据类型相互转换
2.4指针
2.5变量生命期
2.6字符串应用
2.7枚举
2.8类型别名
2.1变量
2.1.1 声明变量
功能:存储用户的数据
注意: 变量必须经过声明才能开始使用
变量声明格式:
标准格式
var 变量名 变量类型
以关键字var开头,后置变量类型,行尾无线分号
- package main
- import ("fmt")
- func main() {
- var a int
- var b string
- var c []float32
- var d func() bool
- var e struct{
- x int
- }
- }
批量格式
使用var关键字 和括号
- package main
- import ("fmt")
- func main() {
- var (
- a int
- b string
- c []float32
- d func() bool
- e struct{
- x int
- }
- )
- }
2.1.2 初始化变量
整型和浮点型变量默认值:0
字符串变量的默认值空字符串
布尔型默认值为bool
切片、函数、指针变量的默认值为nil
1.标准格式
var 变量名 变量类型 = 表达式
- var hp int = 100
2.编译器推导的类型
var hp1 = 100
标准格式基础上,省略int,编译器推导
- var attack = 40
- var defence = 20
- var damageRate float32 = 0.17
- var damage = float32(attack-defence) * damageRate
- fmt.Println(damage)
- // 3.4
3.短变量声明并初始化
hp := 100
注意:变量已经被声明过了,再次声明并赋值,使用短变量声明会编译报错
- var p string
- p := '123'
- fmt.Println(p)
- // 错误信息:no new variables on left side of :=(44.4)
- // var p 声明了p变量, p := '123' 会再次声明并赋值
- hp3 := 50
- fmt.Println(hp3)
2.1.3 多个变量同时赋值
顺序:从左到右
- var a int = 100
- var b int = 200
-
- a, b = b, a
- fmt.Println(a, b) //200 100
2.1.4 匿名变量
匿名变量用一个"_"下滑线表示
只需要在变量声明的地方,用下划线代替即可
- package main
- import ("fmt")
- func main() {
- a1, _ := getData()
- _, b1 := getData()
- fmt.Println(a1, b1)
- }
-
- type IntSlice []int
- // 编写一个len方法,提供切片的长度
- func (p IntSlice) Len() int { return len(p)}
- // 根据提供i,j元素索引,两个元素进行比较,返回比较结果
- func (p IntSlice) Less(i, j int) bool { return p[i] < p[j]}
- // 根据提供i,j元素索引,交换两个元素的值
- func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i]}
-
- func getData() (int, int) {
- return 200, 100
- }
2.2 数据类型
2.2.1 整型
两种: 长度 int8 int16 int32 int64 无符号 uint8 uint16 uint32 uint64
2.2.2 浮点型
两种:float32和float64
- fmt.Println("hello world")
- fmt.Printf("%f\n", math.Pi)
- fmt.Printf("%.2f\n", math.Pi)
2.2.3 布尔型
注意:go不允许将整型类型转换为布尔型, 无法参与数值运算,也无法跟其他类型进行转换
- var n bool
- fmt.Println( int(n) * 2 )
- //cannot convert n (type bool) to type int
2.2.4 字符串
用双引号括起来的内容就是为字符串的内容
- str := "hello world string"
- ch := "中文"
- fmt.Println(str, ch)
- //hello world string 中文
字符串转义符
符合 说明 \r 回车 \n 换行符 \t 制表符 ' 单引号 " 双引号 \ 双斜杠 - fmt.Println( "str := \"c:\\Go\\bin\\go.exe\" ")
- str := "c:\Go\bin\go.exe"
- fmt.Println( "str := \"c:\\Go\\bin\\go.exe\" ")
字符串实现基于utf-8编码
定义多行字符串
- const longstr = `
- 第一行
- 第二行
- \r\n
- 。。。
- `
- fmt.Println(longstr)
- //第一行
- //第二行
- //\r\n
- //。。。
-
- const codeTemplate = ` // Generated by github.com/davyxu/cellnet/protoc-gen-msg
- // DO NOT EDIT!{{range.Protos}}
- // Source:{{.Name}} {{end}}
- package {{.PackageName}}
- {{if gt .TotalMessages 0}}
- import (
- "github.com/davyu/cellnet"
- "reflect"
- _ "github.com/davyxu/cellnet/codec/pb"
- )
- {{end}}
- func init() {
- {{range .Protos}}
- //{{.Name}}{{range .Messages}}
- cellnet.RegisterMessageMeta("pb", "{{.FullName}}")
- reflect.TypeOf((*{{.Name}})(nil)).Elem(), {{.MsgID}}) {{end}}
- {{end}}
- }
- `
- fmt.Println(codeTemplate)
-
2.2.5 字符
字符串中每一个元素都叫字符 两种: 一种为uint8类型
或是 byte类型
代表ascll码的一个字符 另一种为rune类型
, 代表一个UTF-8类型
,实际为int32
用于处理中文、日文等复合字符 使用fmt.Printf 中“%T”
输出变量实际类型,可用于查看byte和rune类型
- var a byte = 'a'
- fmt.Printf("%d %T\n", a, a)
- var b rune = '中'
- fmt.Printf("%d %T\n", b, b)
- //97 uint8
- //20013 int32
2.2.7 切片 -- 能动态分配的空间
一个拥有相同类型元素的可变长的序列
- var name []T
T 代表切片元素类型, 即可以整型、浮点型、布尔型、切片、map、函数等
- t := make([]int, 5)
- t[0] = 1
- t[1] = 2
- t[3] = 3
- fmt.Println(t)
- //[1 2 0 3 0]
- str1 := "hello world"
- fmt.Println(str1[6:])
- //world
2.3 转换不同的数据类型
格式:
T(表达式)
输出各数值范围
- package main
-
- import (
- "fmt"
- "math"
- )
-
- func main() {
- fmt.Println("int8 range:", math.MinInt8, math.MaxInt8)
- fmt.Println("int16 range:", math.MinInt16, math.MaxInt16)
- fmt.Println("int32 range:", math.MinInt32, math.MaxInt32)
- fmt.Println("int64 range:", math.MinInt64, math.MaxInt64)
- int8 range: -128 127
- int16 range: -32768 32767
- int32 range: -2147483648 2147483647
- int64 range: -9223372036854775808 9223372036854775807
-
- //初始化一个32位整型值
- var a1 int32 = 1047483647
- fmt.Printf("int32: 0x%x %d\n", a1, a1)
- //nt32: 0x3e6f54ff 1047483647
- //int32 转为 int16, 发生数值截断
- b1 := int16(a1)
- fmt.Printf("a1 int16: 0x%x %d\n", b1, b1)
- //a1 int16: 0x54ff 21759
- //将常量保存为float32类型
- var c float32 = math.Pi
- //转为int类型,浮点数发生精度丢失
- fmt.Println(int(c))
- //3
- }
2.4 指针
两个核心:
一种是类型指针
,允许对这个指针类型的数据进行修改。 传递数据使用使用指针,而无须拷贝数据 类型指针不能进行偏移和运算
二种是切片
, 由指向起始元素的原始指针、元素数量和容量组成
2.4.1 认识指针地址和指针类型
每个变量在运行时都会被内存分配一个地址,这个地址代表变量在内存中的位置 使用“&”操作符放在变量前面对变量进行“取地址”操作 格式:
- ptr := &variable //variable的类型为T
其中v代表被取地址的变量,被取地址的variable使用ptr变量进行接收,ptr的类型为“T”,称作T的指针类型。“”代表指针
- package main
-
- import (
- "fmt"
- "math"
- )
-
- func main() {
- var cat int = 1
- var str2 string = "banana"
- fmt.Printf("%p, %p\n", &cat, &str2)
- }
- //0xc00004e0e8, 0xc0000421f0 为cat,str2取地址后的指针值
注意:变量、指针和地址三种的关系是:每个变量都拥有地址,指针的值就是地址
2.4.2 从指针获取指针指向的值
对变量“&”取地址操作后获得这个变量的指针,对指针使用“*”操作,就是指针取值
- package main
-
- import (
- "fmt"
- "math"
- )
- func main() {
- var house = "Malibu Point 10880, 90265"
- // 对字符串取地址,ptr1类型为*string
- ptr1 := &house
- // 打印ptr类型
- fmt.Printf("ptr1 类型:%T\n", ptr1)
- // 打印ptr指针地址
- fmt.Printf("ptr1 地址:%p\n", ptr1)
- // 对指针进行取值操作
- value := *ptr1
- // 取值后类型
- fmt.Printf("value 类型:%T\n", value)
- // value值
- fmt.Printf("value:%s\n", value)
- }
- // ptr1 类型:*string
- // ptr1 地址:0xc000042200
- // value 类型:string
- // value:Malibu Point 10880, 90265
-
总结:
取地址“&”和取值“”是一对互补操作符,“&”取地址,"&"根据地址取出地址指向的值
1.对变量进行其地址(&)操作,可获得这个变量的指针变量
2.指针变量的值是指针地址
3.对指针变量进行取值()操作,可以获得指针变量指向的原变量的值
2.4.3 使用指针修改值
x, y := 1,2
- package main
-
- import (
- "fmt"
- "math"
- )
-
- func main() {
- //错误示例
- swap1(&x, &y)
- fmt.Println("x: ",x, "y:", y)
- //x: 1 y: 2
- //正确
- swap(&x, &y)
- fmt.Println("x: ", x, "y: ",y)
- //x: 2 y: 1
- }
- // 交换函数
- func swap(a, b *int) {
- // 取a的指针的值,赋给临时变量t
- t := *a
- //取b指针的值,赋值给a指针指向的变量
- *a = *b
- //a指针的值赋值给b指针指向的变量
- *b = t
- }
-
- // 错误示例
- func swap1(a, b *int) {
- b, a = a, b
- }
2.4.5 创建指针的另一种方法--new()函数
new(类型)
- str3 := new(string)
- *str3 = "ninja"
- fmt.Println(*str3)
- fmt.Println(str3)
- //ninja
- //0xc000042230
2.6 字符串应用
2.6.1 计算机字符串长度 -- len()
go 语言字符串都是以UTF-8格式保存,每个中文占用3个字符
- tip1 := "genji is a ninja"
- fmt.Println(len(tip1))
- // 16
- tip2 := "忍者无敌"
- fmt.Println(len(tip2))
- //12
- // 使用RuneCountInString()统计Uncode字符数量
- fmt.Println(utf8.RuneCountInString("忍者"))
总结
ASCII字符串长度使用len()函数
Unicode字符串长度使用utf8.RuneCountInString()函数
2.6.2 遍历字符串 -- 获取每个字符串
两种写法
遍历每一ASCII字符, 使用for循环遍历
- theme := "阻击 start"
-
- for i := 0; i < len(theme); i++ {
-
- fmt.Printf("ascii: %c %d\n", theme[i], theme[i])
-
- }
- // ascii: é 233
- // ascii: • 152
- // ascii: » 187
- // ascii: å 229
- // ascii: • 135
- // ascii: » 187
- // ascii: 32
- // ascii: s 115
- // ascii: t 116
- // ascii: a 97
- // ascii: r 114
按Unicode字符遍历字符串
- for _, s := range theme {
-
- fmt.Printf("Unicode %c %d\n", s, s)
-
- }
-
- // Unicode 阻 38459
- // Unicode 击 20987
- // Unicode 32
- // Unicode s 115
- // Unicode t 116
- // Unicode a 97
- // Unicode r 114
- // Unicode t 116
总结:
ASCII字符串遍历直接使用下标
Unicode字符串遍历使用for range
2.6.3 获取字符串的某一段字符
string.Index() 在字符串中搜索另一个子串
- tracer := "努力拥抱每一天,不断成长"
- comma := strings.Index(tracer, "每一天")
- posi := strings.Index(tracer[comma:], "成长")
-
- fmt.Println(comma, posi, tracer[comma+posi:])
-
- // 12 18 成长
总结:
strings.Index:正向搜索子字符串
string.LastIndex: 反向搜索自字符串
搜索的起始位置可以通过切片偏移制作
2.6.4 修改字符串
go语言无法直接修改每一个字符元素,只能通过重新构造新的字符串并赋值给原来的字符串变量
- angel := "Hero nerver die"
-
- arrayBytes := []byte(angel)
-
- for i := 5; i <= 10; i++ {
-
- arrayBytes[i] = '-'
-
- }
-
- fmt.Println(arrayBytes)
-
- // [72 101 114 111 32 45 45 45 45 45 45 32 100 105 101]
-
- fmt.Println(string(arrayBytes))
-
- // Hero ------ die
总结
Go语言的字符串是不可以改变的
修改字符串时,可以将字符串转换为[]byte进行修改
[]byte 和string 可以通过强制类型转换互换
2.6.5 连接字符串
可以使用加号“+”连接 可以使用类似于StringBuilder的机制连接,更高效
- hamer := "GO GO GO"
- sickle := "You Can"
-
- // 声明字节缓冲
-
- var stringBuilder bytes.Buffer
-
- // 将字符串写入缓冲区
-
- stringBuilder.WriteString(hamer)
-
- stringBuilder.WriteString(sickle)
-
- //将缓冲以字符串形式输出
-
- fmt.Println(stringBuilder.String())
-
- // GO GO GOYou Can
bytes.Buffer可以缓冲并写入各种字节数组,字符串也是一种字符串数组,使用writeString()
将需要连接的字符串,通过bytes.Buffer声明缓冲stringBuilder调用WriteString()方法写入里面,
再通过stringBuilder.String()方法将缓冲转换为字符串
2.6.6 格式化
写法: fmt.Sprintf(格式化样式,参数列表)
格式化样式:字符串形式,格式化动词以%开头
参数列表:多个参数以逗号分隔,个数必须与格式化中样式个数一一对应
- var progress = 2
- var target = 8
-
- // 两参数格式化
- title := fmt.Sprintf("以完成%d个任务,还差%d个就完成", progress, target)
-
- fmt.Println(title)
- // 以完成2个任务,还差8个就完成
-
- pi := math.Pi
-
- // 按数值本身格式输出
- variant := fmt.Sprintf("%v %v %v", "月球基地", pi, true)
- fmt.Println(variant)
- // 月球基地 3.141592653589793 true
-
- profile := &struct {
- Name string
- HP int
- }{
- Name: "stat",
- HP: 150,
- }
-
- fmt.Printf("使用'%%+v' %+v\n", profile)
- fmt.Printf("使用'%%#v' %#v\n", profile)
- fmt.Printf("使用'%%T' %T\n", profile)
-
- // 使用'%+v' &{Name:stat HP:150}
- // 使用'%#v' &struct { Name string; HP int }{Name:"stat", HP:150}
- // 使用'%T' *struct { Name string; HP int }
base64编码解码示例
- package main
-
- import (
- "fmt"
- "encoding/base64"
- )
-
- func main() {
-
- // 需要处理的字符串
- message := "Away from keyboard. https://golang.org/"
-
- // 编码消息, 传入的字符串需转为字节数组,才能供这个函数使用
- encodeMessage := base64.StdEncoding.EncodeToString([]byte(message))
- // 输出编码完成的消息
- fmt.Println(encodeMessage)
- // 解码消息
- data, err := base64.StdEncoding.DecodeString(encodeMessage)
- // 出错处理
-
- if err != nil {
- fmt.Println(err)
- } else {
- fmt.Println(string(data))
- }
-
- // QXdheSBmcm9tIGtleWJvYXJkLiBodHRwczovL2dvbGFuZy5vcmcv
- // Away from keyboard. https://golang.org/
-
-
- }
2.7 枚举
2.7.1 枚举 -- 一组常量值
- // 使用iota模拟枚举
- type Weapon int
- const (
- Arrow Weapon = iota // 开始生成枚举值,默认为0
- Shuriken
- SniperRifle
- Rifle
- Blower
- )
- // 输出所有枚举值
- fmt.Println(Arrow, Shuriken, SniperRifle, Rifle, Blower)
- var weapon Weapon = Blower
- fmt.Println(weapon)
- // 0 1 2 3 4
- //
2.7.2 枚举--将枚举值转换为字符串
- package main
- import ("fmt")
-
- // 声明芯片类型
- type ChipType int
-
- const (
- None ChipType = iota
- GPU
- CPU
- )
-
- func (c ChipType) String() string {
-
- switch c {
- case None:
- return "None"
- case GPU:
- return "GPU"
- case CPU:
- return "CPU"
-
- }
- return "N/A"
-
- }
-
- func main() {
- // 输出CPU的值并以整型格式显示
- fmt.Printf("%s %d", CPU, CPU)
- //CPU 2
- }
-
2.8 类型别名
2.8.1 区分类型别名与类型定义
类型别名的写法:
type TypeAlias = Type
类型别名规定:
TypeAlias只是Type的别名,本质上TypeAlias与Type是同一个类型
- // 将NewInt定义为int类型
- type NewInt int
- // 将int取一个别名叫IntAlias
- type IntAlias = int
-
- // 将a声明为一个NewInt类型
- var alias_a NewInt
- fmt.Printf("a type: %T\n", alias_a)
- // a type: main.NewInt
-
- // 将a2声明为IntAlias类型
- var alias_a2 IntAlias
- fmt.Printf("a2 type: %T\n", alias_a2)
- // a2 type: int
2.8.2 非本地类型不能定义方法
- 不能为不在同一个包中声明的类型定义方法,即不能为在其他包声明的类型在本地包中定义方法
- package main
-
- import ("time")
-
- // 2.8.2
- // 定义time.Duration 的别名为MyDuration
- type MyDuration = time.Duration
-
- // 为MyDuration 添加一个函数
- func (m MyDuration) EasySet(a String) {
- }
-
- func main() {
- }
- //# 2-base/2.2-data_type
- //.\data_type.go:51:6: cannot define new methods on non-local type time.Duration
- //.\data_type.go:51:31: undefined: String
- //exit status 2
- //Process exiting with code: 1
-
2.8.3 在结构体成员嵌入时使用别名
- package main
-
- import (
- "fmt"
- "reflect"
- )
-
- // 定义商标结构
- type Brand struct {
-
- }
- // 为商标结构添加Show()方法
- func (t Brand) Show() {
-
- }
-
- // 为Brand定义一个别名
- type FakeBrand = Brand
- // 定义车辆结构,嵌入商标结构
- type Vehicle struct {
- Brand
- FakeBrand
- }
-
- func main() {
-
- // 声明变量 a 为车辆类型
- var a Vehicle
- // 指定调用FakeBrand的Show
- a.FakeBrand.Show()
- // 取a的类型反射对象
- ta := reflect.TypeOf(a)
-
- // 遍历a的所有成员
- for i := ; i < ta.NumField(); i++ {
- // ta 成员信息
- f := ta.Field(i)
- // 打印成员的字段名和类型
- fmt.Printf("FieldName: %v, FieldType: %v\n", f.Name, f.Type.Name())
- }
-
- // FieldName: Brand, FieldType: Brand
- // FieldName: FakeBrand, FieldType: Brand
-
-
- }
总结:
FakeBrand是Brand的一个别名,在Vehicel中嵌入FakeBrand和Brand,Vehicel的类型会以名字的方式保留在Vehicle的成员中
FakeBrand和Brand 都有Show()方法, 调用时必须制定调用谁的, a.FakeBrand.Show()
Go语言--基础语法笔记的更多相关文章
- python语言基础语法笔记<note2--面向对象编程>
Python面向对象编程(OOP) 一.面向对象过程的优点特征: 封装 模型的特征和能力打包在一起 模型的改变由模型自身完成 隐藏模型的细节,外界只能使用,不能改变 继承 符合自然界分类规律 快速实现 ...
- python语言基础语法笔记<note1库安装和工具安装>
Python是一门入门简单的编程语言,它的安装和搭建也非常简单.在大部分的发行Linux版本上都预装了python2,部分也预装了python3,需要查看Linux上是否安装Python,只需要在 命 ...
- C语言基础语法
#include <stdio.h> int main() { int age; printf("input your age"); scanf("%d&qu ...
- Smali语言基础语法
1.Smali语言基础语法-数据类型与描述符 smali中有两类数据类型:基本类型和引用类型.引用类型是指数组和对象,其它都是基础类型. 基本类型以及每种类型的描述符: Java类型 类型描述符 说明 ...
- 黑马程序员——OC语言基础语法 面向对象的思想
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结)(一)基础语法 1)关键字 @interface.@implementati ...
- SQL基础语法笔记教程整理
PS:本文适用SQL Server2008语法. 一.关系型数据库和SQL 实际上准确的讲,SQL是一门语言,而不是一个数据库. 什么是SQL呢?简而言之,SQL就是维护和使用关系型数据库中的的数据的 ...
- 黑马程序员——C语言基础语法 关键字 标识符 注释 数据及数据类型
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (一下内容是对黑马苹果入学视频的个人知识点总结) (一)C语言简单介绍 (1)C语言程序是由函数组成的任何C语言程序都是由一 ...
- php语言基础语法与编程工具推荐
php脚本语言,需要在服务器端执行,用浏览器返回HTML结果.在PHP中所有的语法都是如此,用户端是无法修改的,只有浏览权限. 一.php基础语法之输出方法 1.PHP中所有的脚本,可以放在文件中的任 ...
- SQL 基础语法笔记教程整理
最近从图书馆借了本介绍 SQL 的书,打算复习一下基本语法,记录一下笔记,整理一下思路,以备日后复习之用. PS:本文适用 SQL Server2008 语法. 首先,附一个发现的 MySQL 读书笔 ...
随机推荐
- Python一些代码
自定义with open打开文件 # 是使用上下文管理协议自定义open class Open(object): def __init__(self,filepath,mode='r',encodin ...
- Zookeeper+Kafka集群部署(转)
Zookeeper+Kafka集群部署 主机规划: 10.200.3.85 Kafka+ZooKeeper 10.200.3.86 Kafka+ZooKeeper 10.200.3.87 Kaf ...
- 搭建一个MP-demo(mybatis_plus)
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生. 搭建一个简单的MP-demo 1.配置pom.xml ...
- Unity插件系列之二维码
1.二维码常见的生成与识别途径 1.草料二维码 https://cli.im/text 2.在软件中实现生成和扫描二维码 使用zxing实现 zxing是一个用java写的开源项目,zxing.net ...
- [LOJ3084][GXOI/GZOI2019]宝牌一大堆——DP
题目链接: [GXOI/GZOI2019]宝牌一大堆 求最大值容易想到$DP$,但如果将$7$种和牌都考虑进来的话,$DP$状态不好设,我们将比较特殊的七小对和国士无双单独求,其他的进行$DP$. 观 ...
- Python实现常用排序算法
Python实现常用排序算法 冒泡排序 思路: 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完 ...
- 基于VUE框架 与 其他框架间的基本对比
基于VUE框架的基本描述 与 其他框架间的基本对比 2018-11-03 11:01:14 A B React React 和 Vue 有许多相似之处,它们都有: 使用 Virtual DOM 提供 ...
- Mac OSX下安装dlib (Python)
1.在安装Dlib库之前需要安装的库:opencv,numpy 2.安装Xquartz2.7.11 Xquartz是执行Unix程序的图形窗口环境,为了兼容Unix和Linux下移植过来的程序就需要安 ...
- docker基本使用
1.启动执行一次的容器 2.启动交互式容器 -i:告诉docker守护进程始终打开交互输入 -t:给容器分配一个伪tty终端 3.查看容器 docker ps:查看正在运行的容器 docker ps ...
- Linux安装gitbook
安装g++ 默认centos7上是没有安装g++ 通过命令: $ yum -y install gcc openssl-devel gcc-c++ compat-gcc-34 compat-gcc-3 ...