常量

常量定义

可以使用 const关键字指定你想要定义的常量,例如:

1
2
const PI=3.1415926
const PI float64=3.1415926

在定义的时候,你可以指定他的类型,也可以不指定,都可以

预定义常量

Go语言预定义了这些常量,true,false和iota

其中iota比较特殊,可以认为是一个可以被编译器修改的常量;

在第一次使用的时候,就自动置0,在下一个itoa出现以前,其代表的数字会依次+1;

例如:

1
2
3
4
5
6
const(
c=iota //0
c1=iota //1
c2=iota //2 到这里这里的一个const算是结束
)
const c3=iota //0 下一个的开始

如果多个赋值语句一样,比如都是 变量名=iota,那么我们就可以简写这个表达式;

1
2
3
4
5
const(
c0=iota
c1
c2
)

枚举

Go不支持我们Java 的Enum关键字,所以我们可以使用下面这个方式来表示枚举类

1
2
3
4
const(
SUNDAY
MONDAY
)

复数类型

复数实际上是由两个实数构成,一个是实部,一个是虚部

1
2
3
4
var value1 complex64 // 由2个float32构成的复数类型
value1 = 3.2 + 12i
value2 := 3.2 + 12i // value2是complex128类型
value3 := complex(3.2, 12) // value3结果同 value2

.实部与虚部 对于一个复数z = complex(x, y),就可以通过Go语言内置函数real(z)获得该复数的实 部,也就是x,通过imag(z)获得该复数的虚部,也就是y。

1
2
3
4
const a complex64=1+2i
const b=1+2i
fmt.Println(a+b)
fmt.Println(real(a))

字符串

1
2
3
4
5
6
7
8
var str string // 声明一个字符串变量
str = "Hello world" // 字符串赋值
ch := str[0] // 取字符串的第一个字符
fmt.Printf("The length of \"%s\" is %d \n", str, len(str))
fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)
输出结果为:
The length of "Hello world" is 11
The first character of "Hello world" is H.

申明:

求一个字符串的长度使用的是 len(变量名),获取字符串里的某一个位置上的字符,相当于Java里面的charAt()

1
2
3
str:="123456"
ch:=str[0]
fmt.Printf("%c",ch)

需要注意的是,我们的str[index]取出来的ASCII,直接输出会是数字,我们必须使用%c,%s来格式化;直接使用Println输出的字符串

运算 含义 结果
x+y 字符串连接 “hello”+”123”=”hello123”
len(s) 字符串长度 len(“hello”)=5
s[i] 取字符 “Hello”[1]=’e’(这里是字符的单引号)

练习:遍历一个字符串

1
2
3
4
5
str:="i am iron man"
for i:=0;i<len(str);i++{
fmt.Printf("%c"+"\tindex is\t%d",str[i],i)
fmt.Println()
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
i	index is	0
index is 1
a index is 2
m index is 3
index is 4
i index is 5
r index is 6
o index is 7
n index is 8
index is 9
m index is 10
a index is 11
n index is 12

其他数据类型变成字符串

第一种:fmt.Sprintln()

使用 接收者:=fmt.Sprintln(要转换的变量)

1
2
3
a:=1
str:=fmt.Sprintln(a)
fmt.Println(str)

**第二种:使用strconv(string+convert:字符转换) **

1
2
3
a:=1
str:=strconv.FormatInt(int64(a),10)
fmt.Println(str)

func Formatxxxx(xxxx,base int) 返回i的base进制的字符串表示。base 必须在2到36之间,结果中会使用小写字母’a’到’z’表示大于10的数字。如果我们要使用这个类来和字符串进行转换,那么他的数据类型就必须是下面几类;**==int64,uint64,bool,float64==**

简单了解一下这个类:

strconv包实现了基本数据类型和其字符串表示的相互转换。

image-20201205215607559

字符串变成其他的数据类型

使用strconv的parsexxxx

1
2
3
str:="123"
a, _:=strconv.ParseInt(str,10,10)
fmt.Println(a)

如果返回的没有我们想要的类型,那么我们就使用强制类型转换即可

简单分析一下这个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func ParseInt(s string, base int, bitSize int) (i int64, err error) {
const fnParseInt = "ParseInt"

if s == "" {
return 0, syntaxError(fnParseInt, s)
}

// Pick off leading sign.
s0 := s
neg := false
if s[0] == '+' {
s = s[1:]
} else if s[0] == '-' {
neg = true
s = s[1:]
}

base指定进制(2到36),如果base为0,则会从字符串前置判断,”0x”是16进制,”0”是8进制,否则是10进制;

bitSize指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64;返回的err是*NumErr类型的,如果语法有误,err.Error = ErrSyntax;如果结果超出类型范围err.Error = ErrRange。

我们可以初步了解一些我们go函数的返回值是在哪里标出的;

函数格式:func 函数名 (参数)(返回值)**,所以我们在使用这个函数的时候,没有找到变量接收这个函数的返回值,我们就是使用一个 **__下划线的意义是忽略这一个变量,另一个说法就是如果我们不忽略我们就要创建一个对象,但是这个对象我们却不知道会不会用,但是我们的go语言的规则就是创建了就必须使用,如果每一个类似的错误,我们都要使用,未免太难为人了

字符类型

就是我们Java里面的char,在Go语言中支持两个字符类型,一个是byte(实际上是uint8的别名),代表UTF-8字符串的单个字节的值;另一个是rune,代表单个Unicode字符。

数组

数组是Go语言编程中最常用的数据结构之一。顾名思义,数组就是指一系列同一类型数据 的集合。数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数 组的长度。

常见的声明办法:

1
2
3
4
5
[32]byte // 长度为32的数组,每个元素为一个字节
[2*N] struct { x, y int32 } // 复杂类型数组
[1000]*float64 // 指针数组
[3][5]int // 二维数组
[2][2][2]float64 // 等同于[2]([2]([2]float64))

代码实现:

创建一个数组:

1
2
3
4
原始方式:var array [3]int=[3]int{1,2,3}
左边不写变量的类型: var array=[3]string{"hello","world","GO"}
直接使用:= : array:=[3]int{1,2,3}

遍历一个数组的两种方式:

1
2
3
4
5
6
7
8
第一种
for i:=0;i<len(array);i++{
fmt.Println(array[i])
}
第二种
for i,v:=range array{
fmt.Println("下标是",i,"内容是",v)
}

其中,第一种和我们的字符串的遍历一样,另一种就是我们原来的for(变量:变量),在上面的例子里可以看到,range具有两个返回值,第一个返回值是元素的数组下标,第二 个返回值是元素的值。

指针

一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。指针变量通常缩写为 ptr。

从现在的认知来看,就是指针指向一个地址,那个地址上面存的的就是实际上的值;

1
2
3
4
5
6
7
str:="123"
a:=&str
var ptr *string
fmt.Println(a)//指针
fmt.Println(&a)//获得存储指针的地址
fmt.Println(*a)//指针指向的值
fmt.Println(ptr)//没有初始化的指针,默认是nil

结果是:

1
2
3
4
0xc00003a1f0
0xc000006028
123
<nil>

使用 *==&==**获得变量的值,使用 **====**获得指针的值

指针的类型是指向的值的类型,比如str:=&a,那么str的类型就是*int

值类型和引用类型

  • 值类型:基本数据类型int,float,bool,string,数组和结构体
  • 引用类型:指针,slice切片,map,管道chan,interface等都是引用类型

二者的使用特点:

值类型直接存储值,内存一般在栈中,引用类型存储的是一个地址,这个地址对应的空间才是真正的存储的地方,通常在堆中分配

标识符(命名规则)

  • 由英文大小写,数字,下划线
  • 数字不可以开头
  • 严格区分大小写
  • 一个标识符不能中间有空格
  • 不能使用关键字

标识符注意事项:

  1. 包名:包名尽量和目录保持一致,不要和标准库冲突
  2. 变量名、函数名、变量名:采用驼峰命名法;但是要注意首字母不参与这种方式,因为首字母表示权限
  3. 变量名,函数名,常量名首字母如果大写就可以被其他的包访问,相当于public,如果是小写的就是私有的,可以看成private;