在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
《一周学会go语言并应用》 by王奇疏 欢迎加入go语言群: 218160862 (深圳群) , 808784562(南宁go语言技术群) 群内有实践 点击加入 (深圳群),南宁go语言技术群 808784562,欢迎加入。
零、安装go语言,配置环境及IDE 这部分内容不多,请参考我的这篇安装环境《安装go语言,配置环境及IDE》 日常只有2条命令: go run 文件路径/xxx.go 运行go程序 go build 文件路径/xxx.go 编译为二进制文件或exe文件 如果你不想每次都敲这些命令,附送1个《一键编译go文件命令.bat》 只能windows下使用,( 一般情况下,ide也是用同样的原理,ide的运行/编译也是利用这2个命令集成到ide里面 )
go build 命令生成的exe文件(或二进制文件)还是很小的,5M左右。 比c++ c#等要大一些。 这边是Go的1个ide,叫做liteIde,是中国人写的,他还写了1个goqt 界面类库, 很不错。
第一节、语法 1)注释: // 单行注释 /* 多行注释 *// 2). 【基本语法】 一个go语言程序项目只能有1个 package main包、1个main函数, 像C语言一样。用 import 关键字导入类包。 go语言变量和函数名的首字母大写,表示公开的意思,相当于类里面的public属性修饰。小写则不公开,别的package包不能引用。 例子: package main import "fmt" // fmt是标准包,提供基本的打印函数 Println等,类似于C语言里面的 #include <stdio.h> func main( ){ // 大括号不能换行 fmt.Println( "hello world~! go程序,你好。" ) }
go语言代码不需要以分号结束。类包导入后 和 变量定义后必须使用,不然编译器报错。(可以通过下划线符号来回避_) 以下开始,为了省略代码,这些: package mian main(){ } 就不写了。 下面例子中的所有散代码都应该放在 func main(){ ... } 中运行,除了新定义的函数之外。
关于fmt标准包的函数列表,请参考: 《go语言手册.chm》 builtin 这个内置包,里面有详细说明。 go语言手册1.3.3中文.chm 下载 标准输入、输出函数有: fmt.Printf( ) 这个函数按照C语言的printf() 里面的参数, 打印变量。 fmt.Println( ) 这个函数可以 直接打印 【任何变量】,非常好用于调试显示信息。 func Scanf( format string, a ...interface{}) (n int, err error) Scanf从标准输入扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。
3). 操作运算符 支持常见的运算符: + - * / % 逻辑运算符: && || == != ! < <= >= > 二进制运算: & | ~ ^ >> << &^ go的特殊运算符: <- 表示接收传递的信号
字符串连接符是加号: "hello " + " world~! " 赋值运算符: = 和 := (这个是声明并赋值)
// go语言不支持三元运算符 ? : ,需要自己模拟三元运算符函数。!!! 模拟方法,详见第二节:常见用法
4). 变量: go定义变量的时候,是变量名在左边, 类型在右边。 var str string = "字符串" var num int = 10
我想省略 var 和数据类型,写得更简短一点,怎么办呢?使用类型自动推导,定义并赋值给变量: str := "字符串" num := 12 (最常用的就是这种。赋值符号 := , 只能在函数的局部变量中使用,不能在函数外的全局变量中使用)
可以一次定义多个变量 a, b, c, d := 1, 2, 3, 4
特殊变量下划线,在需要不使用变量的时候用到( python等语言中也有这个特殊的弃用变量 ) i := 10 _ = i
5). 常量: const a int = 3 const ( b int = 3 c int = 99 ) // 常量中的枚举. 当使用关键字iota 定义常量组中时,返回: 从常量定义处第n个常量开始计数,自增 const ( d int = 3 e // 如果不提供类型和初始值,那么视作与上1个常量值和类型都相同 i1 = iota // 这个常量是第3个常量,故i1 == 2 ( 从0数起 ) 。关键字 iota导致枚举 从第n-1个常量开始计数 i2 // 等于3 i3 // 等于4 i4 // 等于5 )
// 下面定义一组文件尺寸的单位,从kb到tb const ( // 下列常量按照表达式进行赋值. 表达式与iota结合时,其下的常量都将按照此表达式进行计算。 b int64 = 1 << (10 * iota) // 这条表达式的值是:1 , 此时 iota == 0 ,并与表达式 1 << ( 10 * 0 ) 结合, 故表示2的0次方, kb // 这条表达式的值是:1024 , 此时 iota == 1 ,并与表达式 1 << ( 10 * 1 ) 结合, 【故这条表达式表示: 2的10次方】 mb // 这条表达式的值是:1048576, 此时 iota == 2 ,并与表达式 1 << ( 10 * 2 ) 结合, 【故这条表达式表示: 2的20次方】 gb // 这条表达式的值是:1073741824, 此时 iota == 3 ,并与表达式 1 << ( 10 * 3 ) 结合, 【故这条表达式表示: 2的30次方】 tb // 这条表达式的值是:1099511627776, 此时 iota == 4 , 同上 表示: 2的40次方 )
6). 分支 和 循环 go语言的 if 表达式不需要括号: if true { fmt.Println( "条件为真" ) } else{
}
// 在if中赋值,并判断 if i := 1; i == 1 { fmt.Println( "条件为真" ) }
// 在go语言中switch不需要break来终止,会自动跳出。 只有使用 fallthrough 关键字的时候才会继续往下走。 switch i { case 0: fmt.Printf("0") case 1: fmt.Printf("1") case 2: fallthrough case 3: fmt.Printf("3") default: fmt.Printf("Default") }
【循环遍历】 //一般的for循环 for i := 0; i < 10 ; i++ { fmt.Println( i ) }
// 1维纯数字数组 arr := [...] int { 8, 2, 3, 11, 324, 133, 1, 45, 13, 7, 14 } for i := 0; i < len( arr ); i++ { fmt.Println( arr[ i ] ) }
//使用for range 来循环,相当于别的语言foreach( list k=>v ) // 输出一维索引数组( php中的索引数组,其他语言中的map, json ) myInfo := map[ string ] string { "id":"1", "name":"王奇疏", "sex":"man", } for k, v := range myInfo { fmt.Println( "k=", k, " v=", v ) }
输出: id : 1 name : 王奇疏 sex : man
// 输出二维索引数组( 例如数据库多行记录 或 1个json ) 【这是用原始方式实现字典,还有另1种使用struct方式实现字典】 personList := map[ int ]( map[ string ] string ) { 0: { "name": "李雷", "sex": "man", "age": "18", "birth": "1993-02-18", }, 1: { "name": "韩梅梅", "sex": "women", "age": "19", "birth": "1992-11-03", }, 2: { "name": "王奇疏", "sex": "man", "age": "???", "birth": "xxx-01-11", }, } for i, person := range personList { fmt.Printf( "%d.%s%s今年%s岁,%s\n", i+1, person["name"], ifReturn(person["sex"] == "man", "先生", "女士"), person["age"], ifReturn(person["sex"] == "man", "他今晚决定去酒吧", "她今晚去洗头") ) }
// 模拟三元运算符。 go 不支持三元运算符,需要自己模拟简化!!! 奇葩.这个使用例子是 str := ifReturn( 0 == 1, "0等于1", "0不等于1" ) func ifReturn( condition bool, trueVal, falseVal interface{} ) interface{} { if condition { return trueVal } return falseVal }
输出 1.李雷先生今年18岁,他今晚决定去酒吧 2.韩梅梅女士今年19岁,她今晚去洗头 3.王奇疏先生今年???岁,他今晚决定去酒吧
7). 定义函数 func echo( msg string ) { fmt.Println( msg ) }
// 函数返回值,可以返回多个值. 参数跟变量一样 func sum2( a, b int ) ( int, bool ) { return a + b , true }
func sum( arr []int ) int { // 返回int型的值 sum := 0 for i := 0; i < len( arr ); i++ { sum += arr[ i ] } return sum }
调用函数: arr := [...] int { 8, 2, 3, 11, 324, 133, 1, 45, 13, 7, 14 } total =: sum( arr ) fmt.Println( total )
// func关键字后面可以跟着括号,为类型添加方法 给该函数标明所属的类(面向对象,标明该函数所属的类),来给该类定义方法. 如果没有类的类型,则纯粹是一个函数. // 这里的 obj myClass ,表示给myClass类添加了一个方法。这是面向对象的用法。 func ( obj myClass ) myFun ( str string ) {
}
8). 数据类型 基本类型: 类型 长度 默认值 说明 ---------------------------------------------------------- bool 1 false byte 1 0 uint8 rune 4 0 Unicode Code Point, int32 int,uint 4 8 0 32 或 64 位 int8,uint8 1 0 -128 ~ 127, 0 ~ 255 int16,uint16 2 0 -32768 ~ 32767, 0 ~ 65535
int32,uint32 4 0 -21亿 ~ 21 亿, 0 ~ 42 亿 int64,uint64 8 0 float32 4 0.0 float64 8 0.0 complex64 8 complex128 128
string "" UTF-8 字符串 array 值类型 struct 值类型 slice nil 引用类型 map nil 引用类型
channel nil 引用类型 interface nil 用于表示任意类型的数据类型、或者作为面向对象的【接口】使用 function nil 函数
uintptr 4 或 8 存储指针的 uint32 或 uint64 整数 空指针值为 nil ----------------------------------------------------------
数学上支持八进制、十六进制 表示法,以及科学记数法。标准库 math 定义了各数字类型取值范围。 a, b, c, d := 071, 0x1F, 1e9, math.MinInt16 请参考《go语言手册1.3.3中文.chm》 builtin 这个内置包,里面有数据类型的详细说明。
需要说明的是:数据类型是严格区分的, 数据类型之间只有【互相兼容的类型】才能直接互相赋值,否则:要么通过强制类型转换来赋值,要么需要通过类包来转换。 例如 这样会报错: var i int = 3 var j int64 = i _ = j
报错信息: xxx.go:错误所在的行数 : cannot use i (type int) as type int64 in assignment 说明 int 和 int64 不是1个类型。 类型转换,会在下一节讲到。
第二节、常见用法( 类型转换、常用数组、json map字典、使用第三方类库如mysql ) 让字符串保持原样,不处理转义问题,用1个小引号括起来像这样: str := ` 字符串'"'''''sfsdfsdf `
// go语言不支持三元运算符 ? : ,需要自己模拟三元运算符函数。!!! 奇葩. 这个使用例子是 str := ifReturn( 0 == 1, "0等于1", "0不等于1" ) func ifReturn( condition bool, trueVal, falseVal interface{} ) interface{} { if condition { return trueVal } return falseVal }
1).数据类型之间的转换 ,常用的转换函数 上一节讲到: 数据类型是严格区分的, 数据类型之间只有【互相兼容的类型】才能直接互相赋值,否则:要么通过强制类型转换来赋值,要么需要通过类包来转换。 例如: int 和 int64 不是一个类型。
类型转换的方法, 强制转换:通过 类型名( ) 这种方式强制转换 var i int = 123 var j int64 = int64( i ) _ = j // 定义1个变量,但不使用,让编译器不报错的方法
【go类型转换】 (1). 数据类型是严格区分的, go必须显示调用函数来做类型转换,没有隐式转换的说法。
特别注意 if 条件中只能是bool型,不能是 if 0 之类。 可以用表达式来处理这类 if exp != 0 例如这是错误的: if 0 == false { fmt.Println( " 0等于flase吗?不相等。if中只能使用布尔型进行判断,不能用 0 空等其它类型的值 与 布尔型进行判断" ) } if ! 0 { fmt.Println( " 这也是错的" ) }
if中只能使用布尔型进行判断,不能用 0 空等其它类型的值 与 布尔型进行判断。 可以通过转换为表达式来处理 res := 1 == 1 if res { fmt.Println( "这是正确的" ) }
(2). 只有两种互相兼容的数据类型的变量,才可以使用 类型() 这种方式来进行转换,否则需要使用类库 或者 自行处理。 如: int8和int32 是兼容的,可以使用 int32( i ) 进行转换。 类似的还有 float32( ) 、 string( ) 、 []byte( "abc" )
(3). 其它不兼容的数据类型的转换方法,使用常用的类库进行转换: fmt.sprintf, strconv.Itoa(i) strconv.Atoi(s) , ParseInt() ParseFloat()等 还有就是 强制类型转换表达式, 如 _var.( *int32 ) 这种方式也叫做断言。
fmt.sprintf( ) 将1个变量打印转换为字符串 strconv.Itoa(i) 使用字符串转换类包strconv, Itoa()是表示数字转成字符串( integer to array ) strconv.Atoi(s) 这个是相反,表示字符串 转成 数字( array to integer ) ParseInt() ParseFloat() 解释为数字、浮点数
(4). 常用例子 1、整形到字符串: var i int = 1 var s string s = strconv.Itoa(i) 或者 s = FormatInt(int64(i), 10)
2、字符串到整形 var s string = "1" var i int i, err = strconv.Atoi(s) 或者 i, err = ParseInt(s, 10, 0)
3、字符串到float(32 / 64) var s string = 1 var f float32 f, err = ParseFloat(s, 32) float 64的时候将上面函数中的32转为64即可
4、整形到float或者float到整形, 直接使用float(i) 或者 int(f) 直接进行转换即可
5、 []byte数组 转为字符串: string( buf ) str := string( []byte{ 'a','b','c' } ) // byte转字符串 buf := []byte( "abc" ) // 字符串转byte
【字符串处理】: go的字符串支持直接根据索引 index 截取字符串,例如: str := "hello world" fmt.Print( str[0:5] ) // 从0到第5字节, 相当于php里面的 substr( str, 0, 4 )
tmp
:= fmt.Sprintf("%d", 22221999 ) fmt.Println( tmp[5:] ) //从第6个字节下标开始截取字符串, 相当于php里面的 substr( str, 5, 长度 ) 这个跟python的切片截取是一样一样的,关于切片等下数组还会讲到。
关于go语言的字符串处理,详见go语言中文手册的2个类包: strings 和 strconv ,包括了:Trim Split Join Replace Repeat ToLower ToUpper HasPrefix( php的strpos ) Contains( 包含 ) 、字符串转义Quote(相当于php中的addslashe之类) 等函数,以及类型转换函数。建议学习时候,对这2个类包 大概鸟览一遍。 (5). 类型转换踩过的坑 (暂略)
2). 常用数组、 map字典等操作 前面第一节,语法的时候发过2个例子。
// 1维纯数字数组 arr := [...] int { 8, 2, 3, 11, 324, 133, 1, 45, 13, 7, 14 } for i := 0; i < len( arr ); i++ { fmt.Println( arr[ i ] ) }
// 输出一维索引数组( php中的索引数组,其他语言中的map, json ) myInfo := map[ string ] string { "id":"1", "name":"王奇疏", "sex":"man", } // 这句声明,表示 map[ 索引类型 ] 值类型
for k, v := range myInfo { fmt.Println( "k=", k, " v=", v ) } 输出: id : 1 name : 王奇疏 sex : man
数组、切片、map这几种结构篇幅占用较多,只需要简单掌握 初始化定义和 几个函数即可:len(list), append( ) , cap( ) . 请参考这篇文章学习,相信很快能使用:《go语言的 数组、slice、map使用》
3). 安装第3方类包/类库,如mysql类库。
(1).类包管理 可以给包起别名,或者在包名前面加1个点号.表示省略包名 package main import( "fmt" f ."strconv" // 我们下面调用的 Itoa() ,其实应该是 strconv.Itoa( 123 )才对。 但是这里使用了.号进行省略包名,所以下面就简单了。(除非包名很长,一般不建议省略)
|
请发表评论