wangyishuaideMacBook-Pro:goStu wangyishuai$ rm hello
wangyishuaideMacBook-Pro:goStu wangyishuai$ ls
hello.go
wangyishuaideMacBook-Pro:goStu wangyishuai$ go run hello.go
hello world!
wangyishuaideMacBook-Pro:goStu wangyishuai$ ls
hello.go
有一个小坑,如果import的包不用,编译会报错。比如,fmt包导入了就必须使用,类似的包括变量等。当注释掉第8行代码,在执行会报错,这点严谨性,比Java强多了。
wangyishuaideMacBook-Pro:goStu wangyishuai$ go run hello.go
command-line-arguments
./hello.go:2:8: imported and not used: "fmt"
go的常用关键字(25个)
- var和const :变量和常量的声明
- var varName type 或者 varName : = value
- package and import: 导入
- func: 用于定义函数和方法
- return :用于从函数返回
- defer someCode :在函数退出之前执行
- go : 用于并行
- select 用于选择不同类型的通讯
- interface 用于定义接口
- struct 用于定义抽象数据类型
- break、case、continue、for、fallthrough、else、if、switch、goto、default 流程控制
- chan用于channel通讯
- type用于声明自定义类型
- map用于声明map类型数据
- range用于读取slice、map、channel数据
如上,其实和其他大部分语言都差不多。其中 go、chan、以及sele ct是go的特色和重点,又比如map类似Java的hashmap……其他的也没什么新鲜的,接下来快速过。
go程序的组织模式
go程序类似Java,都是通过package组织,然后每个独立的、可运行的go程序的入口必须都是main函数,也就是main包里的main函数。
变量和常量
使用var关键字
var是go最基本的定义变量方式 ,但是它的变量类型是放在了变量名后面。
如下,格式化打印语句
go;gutter:true;
Printf</p>
<pre><code>
和C语言非常像,其实go就是C语言衍生改进而来,这也是为什么称它为互联网世界中的C语言的原因。
;gutter:true;
package main
import (
"fmt"
)
func main() {
var x int;
x = 1;
fmt.Printf("%d", x);
}
简洁的定义
有时候会觉得总是多写一个var比较烦,那么可以用:=来定义变量(个人感觉也不是想象中的那么简洁……)
package main
import (
"fmt"
)
func main() {
var x int;
x = 1;
fmt.Printf("%d", x);
a, b, c := 1, 2, 3; // 自动判断类型,类似Python
fmt.Println(a, b, c);
}
View Code
这种方式类似Python,省去了写类型的步骤,在go程序中十分常见。但是这样的写法有一个缺点::= 无法用于函数体外部,而var可以。故var也是有存在的必要的。
eclipse直接提示变量y的定义错误,而变量x是ok的。
注意:
1、package和import必须挨着,也就是它们中间不能有其他代码,否则报错。
2、对于没有显式初始化的变量,Go语言总是将零值赋值给该变量。
3、在Go语言中,声明变量的时候,类型名总是在变量名的后面。
const常量
没什么可说的,和C语言一样的用法,唯一不同的就是定义常量时,加类型或者不加都可以,但是注意,最好养成习惯,类型加在常量名后面。
func main() {
fmt.Println(x);
const dashuai string = "dashuai";
const gogogo = 888;
}
View Code
而且,字符串数据类型和Java不太一样,是完全小写的string。下面会说到。
注意:
1、当需要设置多个常量的时候,不必重复使用 const
,可以使用小括号设置 (var同理
)
package main
import (
"fmt"
)
func main() {
var (
a int;
b string;
c bool;
)
fmt.Println(a, b, c) // 0 false
const (
aa = 1
bb = "dada"
cc = true
)
fmt.Println(aa, bb, cc)
}
View Code
数据类型
bool byte complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
无类型的数值常量可以兼容go内置的任何类型的数值
在不同类型数值之间进行运算或者比较操作,需要进行类型转换。类型转换采用 type(value)
的方式,只要合法就能转换成功,即使会导致数据精度丢失。
快速过一下,和Java对比,如下常用的几个:
整型
1、go独有的 rune,其实就是代表了无符号32位整型 unit32。
2、有符号整型 int (依赖于os,可能是int32或者int64)
- int8 [-128, 127]
- int16 [-32768, 32767]
- int32 [-2147483648, 2147483647]
- int64 [-9223372036854775808, 9223372036854775807]
也就是说,go是见名知意,go中可以直接定义xxx位的整型。
3、字节 byte,等价于 uint8
4、无符号整型 uint ,依赖于不同os实现,可以是uint32或者uint64
- uint8 [0, 255]
- uint16 [0, 65535]
- uint32 [0, 4294967295]
- uint64 [0, 18446744073709551615]
- uintptr 一个可以恰好容纳指针值的无符号整型(对32位平台是uint32, 对64位平台是uint64)
可以通过 unsafe.Sizeof
函数实现类似C语言里 sizeof
操作符的功能,查看类型的字节长度。
package main
import (
"fmt"
"unsafe"
)
func main() {
str := "dashuai"
fmt.Println(unsafe.Sizeof(str)) // 16
a := 1
fmt.Println(unsafe.Sizeof(a)) // 8
var b int8 = 1
fmt.Println(unsafe.Sizeof(b)) // 1
var c int32 = 1
fmt.Println(unsafe.Sizeof(c)) // 4
var d int64 = 1
fmt.Println(unsafe.Sizeof(d)) // 8
}
View Codeunsafe
包含了用于获取Go语言类型信息的方法。
浮点类型
1、float32 ,±3.402 823 466 385 288 598 117 041 834 845 169 254 40×1038 计算精度大概是小数点后7个十进制数
2、float64,±1.797 693 134 862 315 708 145 274 237 317 043 567 981×1038 计算精度大概是小数点后15个十进制数
布尔类型 bool(取值true false)
注意区分Java的boolean/Boolean写法,其实是和C语言一样,这里也说下,学习go,就对比着C语言和Java语言,这样用起来是很快的。
布尔值使用内置的true和false。Go语言支持标准的逻辑和比较操作,这些操作的结果都是布尔值。还可以通过 !b
的方式反转变量 b
的真假。也就是逻辑非。
go可直接定义复数
这也是go独有的, complex32、complex64,在针对一些算法的实现时,非常方便,比如傅里叶变换。
func main() {
var x complex64 = 10 + 9i;
fmt.Print(x + x);
}
View Code
complex32复数,实部和虚部都是float32
complex64复数,实部和虚部都是float64
字符串
常用是string定义,Go语言中的字符串是 UTF-8编码格式(当字符为 ASCII 码时则占用 1 个字节,其它字符根据需要占用 2-4 个字节)。
UTF-8 是被广泛使用的编码格式,是文本文件的标准编码,其它包括 XML 和 JSON 在内,也都使用该编码。由于该编码对占用字节长度的不定性,Go 中的字符串也可能根据需要占用 1 至 4 个字节,这与C++、Java 或者 Python 不同。
Go 这样做的好处是:不仅减少了内存和硬盘空间占用,同时也不用像其它语言那样需要对使用 UTF-8 字符集的文本进行编码和解码。
Go语言中字符串的可以使用双引号( ” )或者反引号( )来创建。</p>
<p>双引号用来创建可解析的字符串,所谓可解析的是指字符串中的一些符号可以被格式化为其他内容,如 "\n" 在输出时候会被格式化成换行符, 如果需要按照原始字符输出必须进行转义。</p>
<p>反引号创建的字符串原始是什么样,那输出还是什么,不需要进行任何转义。
<img alt="" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" /><img alt="" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" /></p>
<pre><code>package main
import (
"fmt"
)
func main() {
str := "123"
str1 := "\n"
str2 :=
\n`
str3 := "\\n"
fmt.Println(str) // 123
fmt.Println(str1) // 换行
fmt.Println(str2) // \n
fmt.Println(str3) // \n
}
View Code
注意
1、Go语言中的部分转义字符
\ 反斜线
\’ 单引号
\” 双引号
\n 换行符
\uhhhh 4个16进制数字给定的Unicode字符
2、在Go语言中单个字符可以使用单引号 ‘ 来创建。而且,一个单一的字符可以用一个单一的 rune
来表示(rune是uint32类型)。这也是容易理解的,因为Go语言的字符串是UTF-8编码,其底层使用4个字节表示,也就是32 bit。
格式化字符串
目前为止,使用了 fmt.Printf
和 fmt.Prinfln
,对于前者的使用,就像C语言中的printf函数一样,常用的格式化指令如下:
格式化指令含义 %% %字面量 %b 一个二进制整数,将一个整数格式化为二进制的表达方式 %c 一个Unicode的字符 %d 十进制数值 %o 八进制数值 %x 小写的十六进制数值 %X 大写的十六进制数值 %U 一个Unicode表示法表示的整形码值,默认是4个数字字符 %s 输出以原生的UTF-8字节表示的字符,如果console不支持UTF-8编码,则会输出乱码 %t 以true或者false的方式输出布尔值 %v 使用默认格式输出值,或者使用类型的String()方法输出的自定义值,如果该方法存在的话 %T 输出值的类型
常用的格式化指令修饰符如下:
空白
如果输出的数字为负,则在其前面加上一个减号”-“。如果输出的是整数,则在前面加一个空格。使用%x或者%X格式化指令输出时,会在结果之间添加一个空格。例如fmt.Printf(“% X”, “实”)输出E5 AE 9E#
%#o
输出以0开始的八进制数据%#x
输出以0x开始的十六进制数据+
让格式化指令在数值前面输出+号或者-号,为字符串输出ASCII字符(非ASCII字符会被转义),为结构体输出其字段名-
让格式化指令将值向左对齐(默认值为像右对齐)0
让格式指令以数字0而非空白进行填充
字符串处理包
strings 
包提供了如查找字符串,分割字符串,判断前后缀,判断字符串包含,字符串替换,统计字符串出现的次数等常用操作。
strconv 
包提供了许多可以在字符串和其他类型的数据之间进行转换的函数。例如可以将数字转换为字符串,将数字样式的字符串转换为数值(将字符串 "12345"
转换 int
类型的整数)
这些直接查文档就可以了。
数组 array slice
array可以类比Python的元组,slice可以类比Python的列表,Java的list,很好理解。
package main
import (
"fmt"
)
/*
array用法
*/
func main() {
var x [10]int;
x[0] = 100;
x[8] = 800;
// %v 可以直接遍历打印数组,非常方便,C语言是没有的。非常高级的用法%v,意思是value,同样数组也不能越界使用。
// 如果没有初值,自动设为0
fmt.Printf("%v \n", x);
// 看长度,和Python的len函数一样
fmt.Println(len(x));
var str [5]string;
str[3] = "aaaa";
// 默认初值为空串
fmt.Printf("%v \n", str);
// 如果使用简洁声明,那么可以直接赋值
y := [3]int{1, 2, 3}
fmt.Printf("%v \n", y);
}
View Code
在看下slice,其实它就是一个动态数组
var x [10]int; // 这是一个静态数组,array,之前说过了
var slice_x []int; // 非常明显,不需要显式声明长度
还可以通过从一个数组或在一个已经存在的slice中再次声明slice
xx := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 一个静态数组
z := xx[1:3]; //对xx切片(和Python一样的道理),切片范围是前闭后开区间,也就是截取了2,3。然后截取的结果赋值给数组z,go的数组同样从下标0开始
其实,现在的z就变为了动态数组slice,类似于指针。
同样slice也可以用简洁方式声明,并且配合关键字make去分配内存空间,make用于内建类型(map、slice 和channel)的内存分配,有些类似C语言的malloc。
package main
import (
"fmt"
)
func main() {
x := make([]int, 3, 8); // 长度为3,容量为8
fmt.Printf("%v \n", x); // [0 0 0]
// 会自动扩容
x = append(x, 1, 2, 3, 4, 5, 6, 7, 8);
fmt.Printf("%v \n", x); // [0 0 0 1 2 3 4 5 6 7 8]
fmt.Printf("%v %v \n", len(x), cap(x)); // 11 16
}
View Code
小结
1、总的来说,如下图,可以从一个array声明slice,其实就是指针指向。
2、在Go语言中,字符串支持切片操作,但是需要注意的是:
如果字符串都是由ASCII字符组成,那可以随便使用切片进行操作
如果字符串中包含其他非ASCII字符,直接使用切片获取想要的单个字符时需要十分小心,因为对字符串直接使用切片时是通过字节进行索引的,但是非ASCII字符在内存中可能不是由一个字节组成。如果想对字符串中字符依次访问,可以使用 range
操作符。
另外获取字符串的长度可能有两种含义,一种是指获取字符串的字节长度,一种是指获取字符串的字符数量。
3、字符串支持以下操作:
语法描述 s += t 将字符串t追加到s末尾 s + t 将字符串s和t级联 s[n] 从字符串s中索引位置为n处的原始字节 s[n:m] 从位置n到位置m-1处取得的字符(字节)串 s[n:] 从位置n到位置len(s)-1处取得的字符(字节)串 s[:m] 从位置0到位置m-1处取得的字符(字节)串 len(s) 字符串s中的字节数 len([]rune(s)) 字符串s中字符的个数,可以使用更快的方法utf8.RuneCountInString() [ ]rune(s) 将字符串s转换为一个unicode值组成的串 string(chars) chars类型是[]rune或者[]int32, 将之转换为字符串 [ ]byte(s) 无副本的将字符串s转换为一个原始的字节的切片数组,不保证转换的字节是合法的UTF-8编码字节
指针
通常情况下Go语言中的变量持有相应的值。也就是说,我们可以将一个变量想象成它所持有的值来使用。
其中有些例外:通道、函数、方法、map、切片slice 是引用变量,它们持有的都是引用,也即保存指针的变量。
在go中,值在传递给函数或者方法的时候会被复制一次,对于布尔类型和数值类型来说这so easy,但是对于大型变量却代价很大。而且复制值传参的方式,修改值只是修改了副本,这能保证原始变量不被修改,但也一定程度上增加了修改原始值的麻烦。(和C语言一样的道理,同样go也保留了C语言的指针)
Go语言中有指针,也没什么新鲜东西,同样在每次传递给函数或者方法的只是变量的内存地址,这是非常高效的。而且一个被指针指向的变量可以通过该指针来修改,这就很方便的在函数或者方法中通过指针修改原始变量。
Go语言中的指针操作符也是使用 &
和 *
操作符。
交换两个变量
func swap1(x, y, p *int) {
if *x > *y {
*x, *y = *y, *x
}
*p = *x + *y
}
View Code
map
类比Java的hashmap,在go中,常用于json解码等。map和Java的哈希表一样,必须申请内存,使用make,否则报错
var a map[string]int32;
a["aaaa"] = 111;
fmt.Printf("%v \n", a);
View Code
执行出错,nil就是null,零值。
Original: https://www.cnblogs.com/kubixuesheng/p/7491356.html
Author: dashuai的博客
Title: 互联网世界中的C语言——我的golang学习笔记:1(基础语法快速过)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/536353/
转载文章受原作者版权保护。转载请注明原作者出处!