变量
一般我们使用的基础的属性是:bool
,int
,string
,float
,complex(复数)
一般我们更常用方法2
var a int = 1//声明变量的方法1
message:="123132"//声明变量的方法2
fmt.Println(message)//->123132\n
fmt.Println(a)//->1\n
我们也可以利用相同的方法来声明一个数组,一维数组和二维数组都可以直接声明出来。
但是需要注意的是,go的数组和其他语言一样,是不可延长的,需要一开始定义好长度。
var arr = [5]int{1,2,3} //声明一维数组的方法,数组容量定死,不可延长
var arr2 [5][5]int //声明二维数组的方法,数组容量定死,不可延长
var arr3 = [5]int{1,2,3,4,5}//声明一个容量为5的数组
var index = arr3[2]//访问数组元素
流程控制
这里简单介绍一下关于if else,for,switch case的基本使用方法,和其他语言都差不多。
- if else
num:=9
if num<0{
fmt.Print(num,"is negetive")
}else if num < 10 {
fmt.Println(num,"has 1 digit")
}else {
fmt.Println(num,"has multiple digits")
}
- for
sum := 0
for i:=0; i<10; i++{
sum+=1
}
fmt.Println(sum)
- switch case
i:=2
switch i {
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
default:
fmt.Println("other")
}
结构体
其实这里的结构体,我们可以理解为对象,而结构体里的参数,就可以理解为对象的属性。
func main() {
//TODO... 结构体
// 结构体
type person struct {
name string
age int
gender string
}
//给结构体赋值
p:= person{name:"Bob",age:42,gender:"man"}
fmt.Println(p)
}
函数与方法
在这里需要强调一下,在go里面的函数和方法是有显著不同的,但是我们可以说方法是特殊的函数。
先看一下函数的demo.
我们可以发现,函数的结构是 func 函数名(参数 参数类型)返回值{函数体}
func main(){
//TODO... 函数(返回一个参)
fmt.Println(add(2,1))
//TODO... 返回两个参
sum2,message := add2(2,1)
fmt.Println(sum2,message)
}
func add2(i int, i2 int) (int, string) {
return i+i2,"successful return"
}
func add(i int, i2 int) int {
c:=i+i2
return c
}
然后我们再来看看方法的Demo,根据网上的资料说,方法的内部不能添加基本的数据的类型,像a int b float这样的就不行,必须得是非基本数据类型。
type person struct {
name string
age int
gender string
}
func (p *person) describe() {
fmt.Printf("%v is %v years old." ,p.name,p.age)
}
func (p *person) setAge(age int) {
p.age = age
}
func (p person) setName(name string) {
p.name = name
}
func main() {
pp:=&person{"Bob",17, "man"}
pp.describe()
//=> Bob is 17 years old
pp.setAge(28)
// =>28
pp.setName("zhangsan")
// =>Bob(之所以值不变,是因为age返回类型是指针,name返回类型的值)
}
闭包
func main() {
add_func := addTest(1,2)
fmt.Print(add_func())
}
//闭包
func addTest(x1 int,x2 int) func()(int,int){
i:=0
return func() (int,int) {
i++
return i,x1+x2
}
}
切片(Slice)与子切片
而如果我们需要定义一个可延长“数组”,就可以使用切片的定义。在这里我个人感觉切片的定义更像是链表。
切片的定义是:不管你是否设置了初始值,都是可以进行延长的。更像是一种数组的抽象。切片包含三个组件:容量,长度和指向底层数组的指针,如下图所示:
我们可以通过append方法和copy方法,对切片的容量进行扩充,append主要功能是延长,而copy是将更大容量的作为载体,将原来的复制过来。
var b []int //声明一个切片的方法1,可以延长
numbers:=make([]int,5,10)//声明一个切片并定义长度,容量的切片(即使定义长度和容量也是可延长的)
//切片是数组的抽象,包含长度,容量和指向底层数组的指针
numbers = append(numbers,1,2,3,4)//在切片末尾添加值,并在有必要的时候增加容量
numbers2 := make([]int,15)//创建容量为15的空切片
copy(numbers2,numbers)//将原始切片复制到新切片
而单纯的去创建一个切片,可能不能很好的满足我们的需求,更灵活的使用方法,是使用子切片。
创建子切片的的基础,使我们有一个切片,对于切片去创建子切片
number2 := []int{1,2,3,4}//创建一个切片,并且赋值
fmt.Println(number2)// -> [1,2,3,4]
//创建子切片
slice1 :=number2[2:]//后两个
fmt.Println(slice1) // -> [3,4]
slice2 :=number2[:3]//前三个
fmt.Println(slice2)// -> [1,2,3]
slice3 :=number2[1:4]//1-4个
fmt.Println(slice3)// -> [2,3,4]
Map
Go的Map和其他的map是一样的,也都是kv键值对的数据结构。
m := make(map[string]int)//创建一个map,k是string,value是int类型
m["string1"] = 2 //添加一个map,key为"string1",value为2
m["string2"] = 3
m["string3"] = 4
for mapIndex := range m {//遍历map元素
fmt.Println(mapIndex,"对应的value是",m[mapIndex])
}
//删除map的某一行
delete(m,"string")
从上面的案例我们也可以看出,go的foreach表达方法是for i : range arr
接口
和普通的其他oop的语言差的不多,也是声明一个接口,然后实现出来。
type animal interface {
description() string
}
type cat struct {
Type string
Sound string
}
type snake struct {
Type string
Poisonous bool
}
func (s snake) description() string {
return fmt.Sprintf("Poisonous : %v",s.Poisonous)
}
func (c cat) description() string {
return fmt.Sprintf("Sound: %v",c.Sound)
}
func main() {
var a animal
a = snake{Poisonous:true}
fmt.Println(a.description())
//=> Poisonous: true
a = cat{Sound: "Meom!!!"}
fmt.Println(a.description())
//=> Sound: Meow!!!
}