这是学习Go语言的第一篇笔记,主要学习的是变量和基本数据类型。如果您也在开始学习Go语言,那么这篇笔记一定能帮助您学习的更快!
我的语言学习过程一般分为下面几个:
1. 变量和数据类型 2. 流程控制方法 3. 函数声明和调用 4. 面向对象 5. 语言特性 6. 标准库
变量声明
Go语言的变量声明有三种
第一种,var identifier type
// 先声明后赋值 var identifier type identifier = value // 声明并且赋值 var identifier type = value
开始实战一下!比如声明一个int类型变量
var i int i = 1 // 或者 var i int = 1
第二种,var identifier = value
第二种不显式声明类型直接赋值。Go语言可以自动推导变量类型。比如
var i = 1 var j = 'str'
第三种,identifier := value
第三种是用来声明一个新的变量,好处就是用这个可以避免覆盖前面有值的变量,保证这个变量一定是一个新的变量。
比如 i:=1。关于这种声明方式,如果之前已经声明过的变量,再次使用将会编译错误。比如
var i i := 1
这种编译的时候会报错。
写一个完整的Go程序!
package main import "fmt" func main() { i:=1 fmt.Println(i) }
疑问,为什么变量声明要把类型放在变量后面呢?
数据类型
Go是一种强类型的语言,不同的数据选择不同的类型能够有效利用内存!
字符串型: string 字节类型: byte(uint8) 数字类型: int uint float32 float64 complex64 complex64 uint8 uint16 uint32 uint64 int8 int16 int32 int64 rune(int32) uintptr 布尔类型: bool 派生类型: 指针类型(Pointer) 数组类型 结构体类型 Channel类型 函数类型 切片类型 接口类型(Interface) Map类型
字符串类型,字节类型,数字类型,布尔类型构成了Go语言的基础类型。这也是大多数语言的基础类型。
挑几个重点数据类型做笔记!
字符串
字符串是一个非常常见的数据类型,几乎所有的语言都有这个数据类型。在Go语言中,字符串和数组类似,但是它是一个不可改变的数组!
概念:字符串是不可改变的字节序列!意味着字符串不可修改!
// 定义一个字符串 var str string = "hello, 这是一个字符串" fmt.Println(str) // 输出 "hello, 这是一个字符串" fmt.Println(str[0]) // 输出104。这是h的ascii值
指针类型
概念:指针变量存储的是一个变量的内存地址!只能把地址赋值给这种变量
比如定义一个int型的变量,var i int = 1,那么可以定义一个int类型的指针来指向i的地址
// 声明一个指针变量 var ptr *int var i int = 1 // &是取地址运算符,把i的地址赋值给 ptr = &i fmt.Printf("i=%d, ptri=%x, prti value=%d", i, ptri, *ptri)
&为取地址运算,*为取地址中的值运算!
常量
和一般语言一致,常量是在运行时不可修改的量。常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
声明一个常量
const identifier [type] = value
type可以省略,让编译器自动推导
数组(定长数组)
数组实际上就是一堆同类型数据的集合,在内存中的位置也是连续的。定义一堆同类型的变量用数组再合适不过啦!
// 声明一个长度为10的int型数组 var i [10] int // 声明一个长度为10的float32型数组 var j [10] float32
上面仅仅是声明了一个数组,并未赋值,因此直接访问会全部是0(数字类型的没有初始化总是0)。要赋值也很简单,直接 i[index] = value这种方式就可以赋值啦。
创建一个一维数组
// 1. 初始化一个长度为5的int类型数组 var i = [5] int {1,2,3,4,5} // 2. 不写长度,让编译器自己算 var i = [...] int {1,2,3,4,5,6}
创建一个多维数组
var value [SIZE1][SIZE2]...[SIZEN] identifier
比如创建一个int类型的二维数组
var i [2][3] int {{1,2,3}, {2,3,4}}
切片(变长数组)
数组的长度一旦声明就不可变,但是很多场景下需要让数组的长度随着程序的运行动态变化。因此Go提供了一个可变长度的数组,称为切片。
概念:切片是可变的数据类型 (联系一下字符串的不可变性)
var identifier []type // 还可以使用make来初始化一个切片 var slice []type = make([]type, len) // 或者简写为 slice := make([]type, len)
实际上,这就定义了一个切片了。Go为切片定义了一系列能够修改数组的操作!
// 定义一个切片 s := []int {1,2,3,4} // 截取切片中的一段,区间为左闭右开 s = s[startIndex:endIndex] // 截取从某个位置开始到最后的区间 s = s[startIndex:] // 截取从开始到某个位置结束 s = s[:endIndex] // 追加 s = append(s, 5) // 追加多个值 s = append(s, 5,6,7)
截取切片中的一段直接引用原数组,没有开辟新的内存,非常高效!在切片上追加一个新的值,只要切片容量足够就不会开辟新的内存空间!
Map(集合/索引数组/关联数组)
Map表示无序键值对集合。在其他语言中,通常也能看到这种身影,称呼可能有索引数组,字典等。不管称呼怎样,内部实现几乎是一致的,即通过hash表来实现。
// 使用make创建map 变量名 := make(map[key类型]值类型)
实战演练一下!
cities := make(map[string]string) cities["北京"] = "北京是中国的首都,也是我家所在的地方" cities["江西"] = "江西是我的老家" cities["湖北"] = "2020中国新冠肺炎最严重的一个城市" fmt.Println(cities["北京"]) fmt.Println(cities["江西"]) fmt.Println(cities["湖北"])
Go语言为Map这种数据类型定义了一些操作,这些操作有:delete(删除操作)
// 删除操作 delete(Map变量名, key) // 例如 delete(cities, "湖北")
还记得对于int,string等一些简单的类型我们可以用var i int, i = 1这种类似的方法去赋值,那么对于map这样可以吗?比如
var cities map[string]string
cities["beijing"] = "北京" // panic: assignment to entry in nil map
这样会导致panic异常。空map是不允许直接赋值的。这里我们需要使用make来为map分配内存之后才可以进行赋值。
以下内容是学习函数后记下的笔记,如果您看到这儿,建议学习函数之后再回来看。
变量作用域
Go语言变量作用域可分为:局部、全局。
全局变量
函数体外定义的变量为全部变量,在任何函数都可使用和被修改!
局部变量
函数内部定义的变量为局部变量,作用域只限于函数内!在函数体内,可以定义和全局变量一样的变量名,这是一个局部变量,并且在函数体内会被优先使用。
实战演练
package main import "fmt" // 定义全局变量 var sword string = "一把剑" var kongfu string = "所有人都会功夫" func main() { iSay() my := getSword() fmt.Printf("我拥有: %s\n", my) fmt.Printf("所有人都有: %s\n", sword) } func iSay() { fmt.Println(kongfu) } func getSword() string { // 定义局部变量 sword := "倚天剑" return sword }
// 输出 所有人都会功夫 我拥有: 倚天剑 所有人都有: 一把剑
以下内容是学习面向对象后记下的笔记,如果您看到这儿,建议看完面向对象之后再回来看。
Go Struct 复合数据类型
使用数组可以定义一组同数据类型的数据。不过如果要定义一本书,这本书有作者,标题,价格等信息,用单一类型显然就不能表示。这时候就需要使用符合数据类型。
Go语言中使用type来定义复合数据类型。
type 结构体类型 struct { 成员1 类型1 成员2 类型2 ... 成员n 类型n }
比如上面说的定义一本书
type Book struct { name string author string price int } // 赋值 book := Book{name: "Go秘籍", author: "imhuchao", price: 0} fmt.Println(book) // 访问成员 fmt.Println(book.name) // 给成员赋值 book.price = 99 fmt.Println(book.price)
Go Interface 接口
Go Interface也是一个数据类型,看看怎样定义一个接口!
// 定义一个接口 type 接口名 interface { 接口方法 返回值 } // 比如定义一个人类接口 type Human interface { say() string }
任何类型,只要实现了这个接口里面的方法,就相当于实现了这个接口。
实战演练一下
package main
import "fmt"
type Human interface {
say() string
}
type Man struct {
}
type Woman struct {
}
func (m Man) say() string {
return "我是个男人"
}
func (w Woman) say() string {
return "我是个女人"
}
func main() {
var man Human
var woman Human
man = new(Man)
woman = new(Woman)
fmt.Println(man.say())
fmt.Println(woman.say())
}
你可能还喜欢下面这些文章
new 和 make 是两个内置函数,主要用来创建并分配类型的内存。在我们定义变量的时候,可能会觉得有点迷惑,不知道应该使用哪个函数来声明变量,其实他们的规则很简单,new 只分配内存,make 只能用于 slice、map 和 channel 的初始化。下面我们就来具体介绍一下new在Go语言中,new 函数描述如下:从上面的代码可以看出,new 函数只接受一个参数,这个参数是一个类型,并且返回一个指向该类型内存地址的指针。同时 new 函数会把分配的内存置为零,也就是类型的零值。【示例】使用 new 函数为变量分配内存空间。当然,new 函数不仅仅能够为系统默认的数据类型,分配空间,自定义
这是我的C++学习笔记第一篇,同所有的程序语言学习路径一样,首先学习的是变量和数据类型。我的学习路径如下:1. 变量和数据类型2. 流程控制3. 函数声明和调用4. 面向对象5. 标准库这一章,学习的是变量和数据类型,需要了解的有:了解这些,对于变量基本就够了。Hello world在开始之前,先写一个hello world来熟悉一下程序的主要结构以及如何打印一个变量。iostream提供标准输入输出的头文件,程序以main函数问入口,std为标准库的命名空间,“<<” 为输出操作符,std::cout为标准输出,std::endl为结束符,表示将等待输出的内容从内存传送到标准输出
shell可以自定义变量,这为shell的编写带来很多方便定义变量定义变量时,变量名不加美元符号($),如:variableName="value"注意:变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样同时,变量名的命名须遵循如下规则。首个字符必须为字母(a-z,A-Z)。中间不能有空格,可以使用下划线(_)。不能使用标点符号。不能使用bash里的关键字(可用help命令查看保留关键字)。变量定义举例:myUrl="http://imhuchao.com/tag/bash"myNum=100使用变量使用一个定义过的变量,只要在变量名前面加美元符号($)即可,如:your_nam
这是我的Go学习笔记的第四篇,面向对象!现代语言几乎都会面向对象进行了支持!当然,Go也具备面向对象的特性!我的语言学习过程一般分为下面几个:1. 变量和数据类型2. 流程控制方法3. 函数声明和调用4. 面向对象5. 语言特性6. 标准库Go语言中的面向对象有点特殊。在Go语言里面,没有显式的class、extends等面向对象语言经常使用的关键词,但是却有面向对象的特性。看看Go怎么实现的把!创建一个类按照我的理解,类实际上就是某种模板,这个模板里面含有有限多个属性和方法。在Go里面,定义这个模板的语法使用type来实现!比如单个int类型可以构成一个类(没错,你甚至可以在int数据类型上
这是我的Go学习的第六篇笔记,也是Go入门的最后一篇笔记。在大多数语言中,了解了变量和数据类型,流程控制,函数,面向对象,再加上标准库,就可以用这门语言去写一些项目了。首先让我想想,在工作中通常会用语言频繁处理什么问题或者处理什么数据?最常见的应该是各种字符串操作,日期和时间,读写文件、socket等IO相关的操作!字符串处理 — StringsString提供了一组处理字符串的操作,常用的有:判断一个字符串是否在另一个字符串中分割字符串为[]string和组合[]string为一个字符串字符串替换...太多了,就不一一列举了,这里列出一些常用的字符串操作。字符串判断字符串分割与合并字符串转换
程序员难免要经常画流程图,状态图,时序图等。以前经常用 visio 画,经常为矩形画多大,摆放在哪等问题费脑筋。有时候修改文字后,为了较好的显示效果不得不再去修改图形。今天介绍的工具是如何使用 Sublime + PlantUML 的插件画流程图,状态图,时序图等。这是一种程序员看了就会爱上的画图方式:自然,高效。什么是 PlantUMLPlantUML 是一个画图脚本语言,用它可以快速地画出:时序图流程图用例图状态图组件图简单地讲,我们使用 visio 画图时需要一个一个图去画,但使用 PlantUML 只需要用文字表达出图的内容,然后就可以直接生成图片。看一个最简单的例子:软件安装这些软件
Go中使用json.Unmarshal interface{}之后的数据类型
有时候设计不好的情况下,一个json类型很难用固定的数据结构去表示,因此我们会用interface{}去表示它。在使用inteface的时候,需要了解json的数据类型对应的go的默认类型,使用才会不会出现疑惑,它们的类型关系对应如下JSONGobooleanbool数值float64字符串stringarray[]interface{}objectmapinterface{}nullnil了解他们默认的类型转换,使用时候就不会出问题了。
编译步骤gcc 与 g++ 分别是 gnu 的 c & c++ 编译器。gcc/g++ 在执行编译工作的时候,总共需要4步:预处理,生成 .i 的文件将预处理后的文件转换成汇编语言, 生成文件 .s 有汇编变为目标代码(机器代码)生成 .o 的文件连接目标代码, 生成可执行程序 参数详解-x language filename参数含义为指定文件所使用的语言。根据约定,C语言的后缀名称为".c",而 C++ 的后缀名为".cpp"或".cc",但如果你的源代码后缀不约定的那几种,那么需要使用-x参数来指定文件所使用的语言。这个参数对他后面的文件名都起作用。 可以使用的参数吗有下面的这些:
python的基本数据类型有整型,浮点型,字符串,布尔,列表,元组,字典,集合。它们占用内存和定义方式如下表:类型占用内存如何定义整型(int)动态长度>=24字节a = 1浮点型(float)动态长度>=24字节a = 1.0字符串(string)动态长度,>=37字节,增加一个字符加1字节a = 'str'布尔(boolean)24字节a = True列表(list)动态长度,>=72字节a = []元组(tupe)动态长度,>=56字节a = ()集合(set)动态长度,>=232字节a = set([])占用的内存通过sys.getsizeof()获
PHP转Go的程序员很多,使用Go重写Web应用,代价不高,并且所带来性能的提升很明显,因此很多PHP程序员正在转Go。PHP是一个弱类型,解释型的语言,Go是一个强类型,编译型语言,两者的差别很大。如果长期使用PHP,使用Go的时候,一些惯性思维会带来不太好的效果。这里总结一些从PHP转到Go需要注意的点。警惕内存越界访问一个数组,在php中,如果a是一个空数组,直接访问a会出现警告,但程序还能继续运行,而在Go中,由于访问一个不存在的地址,程序会直接崩溃。因此Go中需要时刻警惕内存越界。在访问数组下标的时候,如果不能确认需要访问数据一定存在,那么一定要使用len判断数组长度,需要访问的下标
赞赏微信赞赏支付宝赞赏