package main
import (
"container/list"
"fmt"
"math"
"sort"
"strings"
"sync"
)
const (
Unknown = 0
Female = 1
Male = 2
)
func main() {
var (
a int
b string
)
c := 10
d := 20
//交换变量值
d, c = c, d
fmt.Println(d)
fmt.Println(c)
fmt.Println(a)
fmt.Println(b)
fmt.Println("hello world")
e, _ := getData()
_, f := getData()
fmt.Println(e)
fmt.Println(f)
//g1 := true
//使用反引号`定义多行字符串:
var temp string
temp = `
x := 10
y := 20
z := 30
fmt.Println(x, " ", y, " ", z)
x, y, z = y, z, x
fmt.Println(x, " ", y, " ", z)
`
fmt.Println(temp)
//Go语言数据类型转换
//浮点型与整型之间的转换
chinese := 90
english := 80.9
avg := (chinese + int(english)) / 2
avg2 := (float64(chinese) + english) / 2
fmt.Printf("%T, %d\n", avg, avg)
fmt.Printf("%T, %f\n", avg2, avg2)
//:在Go语言中,不允许字符串转 int,否则会产生如下错误。
//常量
fmt.Println(Unknown, Female, Male)
var aa bool = true
var ba bool = false
if aa && ba {
fmt.Printf("第一行 - 条件为 true \n")
}
if aa || ba {
fmt.Printf("第二行 - 条件为 true \n")
}
num := 20
if num%2 == 0 {
fmt.Println(num, "是偶数")
} else {
fmt.Println(num, "是奇数")
}
//在定义时调用匿名函数
func(data int) {
fmt.Println("hello", data)
}(100)
// 将匿名函数赋值给变量
ff := func(datas string) {
fmt.Println(datas)
}
ff("将匿名函数赋值给变量")
//匿名函数用作回调函数
// 调用函数,对每个元素进行求平方根操作
arr := []float64{1, 9, 16, 25, 30}
// 调用函数,对每个元素进行求平方根操作
visit(arr, func(v float64) {
v = math.Pow(v, 2)
fmt.Printf("%.0f \n", v)
})
var nums = [...]int{1, 2, 3, 4, 5}
fmt.Printf("数组 a 的长度为 %d,数组 b 的长度为 %d\n", len(nums), len(nums))
//遍历数组方式1
for i := 0; i < len(nums); i++ {
fmt.Print(nums[i], "\t")
}
fmt.Println()
//遍历数组方式2
for _, value := range nums {
fmt.Print(value, "\t")
}
//三行 每行4个值得二维数组
erweiarr := [3][4]int{
{0, 1, 2, 3}, /* 第一行索引为0 */
{4, 5, 6, 7}, /* 第二行索引为1 */
{8, 9, 10, 11}, /* 第三行索引为2 */
}
fmt.Println(erweiarr)
//声明切片
/*创建切片*/
numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
fmt.Printf("len=%d cap=%d slice=%v \n", len(numbers), cap(numbers), numbers)
/*打印子切片从索引1(包含)到索引4(不包含)*/
fmt.Println("numbers[1:4] ==", numbers[1:4])
/*默认下限为0*/
fmt.Println("numbers[:3] ==", numbers[:3])
/*默认上限为len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:])
/*打印子切片从索引0(包含)到索引2(不包含)*/
number2 := numbers[:2]
fmt.Println("number2 ==", number2)
/*打印子切片从索引2(包含)到索引5(不包含)*/
number3 := numbers[2:5]
fmt.Println("number3 ==", number3)
//定义数组
arrr := [3]int{1, 2, 3}
//根据数组截取切片
nums1 := arrr[:] //数组转为切片
nums2 := arrr[:]
fmt.Println("arrr=", arrr)
nums1[0] = 100
fmt.Println("arrr=", arrr)
nums2[1] = 200
fmt.Println("arrr=", arrr)
//Go语言len()和cap():获取切片长度和容量
//切片的长度是切片中元素的数量。切片的容量是从创建切片的索引开始的底层数组中元素的数量。切片可以通过 len() 方法获取长度,可以通过 cap() 方法获取容量。数组计算 cap() 结果与 len() 相同,具体使用细节如下所示。
arr0 := [...]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}
fmt.Println("cap(arr0)=", cap(arr0), arr0)
//截取数组, 形成切片
s01 := arr0[2:8]
fmt.Printf("%T\n", s01)
fmt.Println("cap(s01)=", cap(s01), s01)
s02 := arr0[4:7]
fmt.Println("cap(s02)=", cap(s02), s02)
//截取切片, 形成切片
s03 := s01[3:9]
fmt.Println("截取s01[3:9]后形成s03:", s03)
s04 := s02[4:7]
fmt.Println("截取s02[4:7]后形成s04:", s04)
//切片是引用类型
s04[0] = "x"
fmt.Print(arr0, s01, s02, s03, s04)
numberse := make([]int, 0, 20)
numberse = append(numberse, 0)
fmt.Println("numberse= ", numberse)
/*同时添加多个元素*/
numberse = append(numberse, 2, 3, 4, 5, 6, 7)
fmt.Println("numberse= ", numberse)
//追加一个切片
s1 := []int{100, 200, 300, 400, 500, 600, 700}
numberse = append(numberse, s1...)
fmt.Println("numberse= ", numberse)
//删除第一个元素
numberse = numberse[1:]
fmt.Println("numberse= ", numberse)
//删除最后一个元素
numberse = numberse[:len(numberse)-1]
fmt.Println("删除最后一个元素= ", numberse)
var country = map[string]string{
"China": "关联数组",
"Japan": "Tokyo",
"India": "New Delhi",
"France": "Paris",
"Italy": "Rome",
}
fmt.Println(country)
for k, v := range country {
fmt.Println("国家", k, "首都", v)
}
//查看元素在集合中是否存在
//可以通过 key 获取 map 中对应的 value 值。语法为:map[key]。
// 当 key 不存在时,会得到该 value 值类型的默认值,
// 比如 string 类型得到空字符串,int 类型得到 0,程序不会报错。
// 所以可以通过value, ok := map[key]获知 key/value 是否存在。ok 是 bool 型,如果 ok 是 true,则该键值对存在,否则不存在。
value, ok := country["England"]
if ok {
fmt.Println("首都:", value)
} else {
fmt.Println("首都信息未检索到!")
}
//或者
if value, ok := country["Japan"]; ok {
fmt.Println("首都 :", value)
} else {
fmt.Println("首都信息未检索到!")
}
//2. 根据key删除map中的某个元素
if _, ok := country["Italy"]; ok {
delete(country, "Italy")
}
fmt.Println(country)
//判断是否包含子串
fmt.Println(strings.Contains("seafood", "foo"))
//将字符串 s 每个单词首字母大写返回
fmt.Println(strings.Title("her royal highness"))
//将字符串 s 转换成大写返回
fmt.Println(strings.ToTitle("louD noises"))
//按字典顺序比较a和b字符串大小
fmt.Println(strings.Compare("abc", "bcd"))
fmt.Println("abs" < "bcd")
//判断s和t两个UTF-8字符串是否相等, 忽略大小写
fmt.Println(strings.EqualFold("Go", "go"))
//将字符串s重复count次返回
fmt.Println("g" + strings.Repeat("o", 8) + "le")
//将a中的所有字符连接成一个字符串, 使用字符串sep作为分隔符
s := []string{"abc", "ABC", "123"}
fmt.Println(strings.Join(s, ", "))
fmt.Println(strings.Join(s, ";"))
ss := "hel" + "lo,"
ss += "world!"
fmt.Println(ss) //输出 “hello, world!”
// 创建一个整型切片,并赋值
slice := []int{10, 20, 30, 40}
// 迭代每一个元素,并显示其值
for index, value := range slice {
fmt.Printf("Index: %d Value: %d\n", index, value)
}
// 声明一个二维整型切片并赋值
erslice := [][]int{{10}, {100, 200}}
fmt.Println("声明一个二维整型切片并赋值", erslice)
// 为第一个切片追加值为 20 的元素
erslice[0] = append(erslice[0], 30)
fmt.Println("为第一个切片追加值为 30 的元素", erslice)
//访问map中的每一个键值对
scene := make(map[string]int)
scene["route"] = 66
scene["brazil"] = 4
scene["china"] = 960
for k, v := range scene {
fmt.Println(k, v)
}
// 声明一个切片保存map数据
var sceneList []string
// 将map数据遍历复制到切片中
for k := range scene {
sceneList = append(sceneList, k)
}
// 对切片进行排序
sort.Strings(sceneList)
// 输出
fmt.Println(sceneList)
//在并发环境中使用的map
//Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构。
/*sync.Map 有以下特性:
无须初始化,直接声明即可。
sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。
使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。*/
var scenebf sync.Map
// 将键值对保存到sync.Map
scenebf.Store("greece", 97)
scenebf.Store("london", 100)
scenebf.Store("egypt", 200)
// 从sync.Map中根据键取值
fmt.Println(scenebf.Load("london"))
// 根据键删除对应的键值对
scenebf.Delete("london")
// 遍历所有sync.Map中的键值对
scenebf.Range(func(k, v interface{}) bool {
fmt.Println("iterate:", k, v)
return true
})
//list(列表)
/*初始化列表
list 的初始化有两种方法:分别是使用 New() 函数和 var 关键字声明,两种方法的初始化效果都是一致的。
1) 通过 container/list 包的 New() 函数初始化 list
变量名 := list.New()
2) 通过 var 关键字声明初始化 list
var 变量名 list.List
给 list 添加元素:*/
//双链表支持从队列前方或后方插入元素,分别对应的方法是 PushFront 和 PushBack
l := list.New()
l.PushBack("fist")
l.PushFront(67)
// 尾部添加
l.PushBack("canon")
// 头部添加
l.PushFront(67)
// 尾部添加后保存元素句柄
element := l.PushBack("fist")
// 在fist之后添加high
l.InsertAfter("high", element)
// 在fist之前添加noon
l.InsertBefore("noon", element)
// 使用
l.Remove(element)
//遍历列表——访问列表的每一个元素
//遍历双链表需要配合 Front() 函数获取头元素,遍历时只要元素不为空就可以继续进行,每一次遍历都会调用元素的 Next() 函数,代码如下所示。
for i := l.Front(); i != nil; i = i.Next() {
fmt.Println("list:",i.Value)
}
//使用结构体类
//顺序初始化,每个结构体中定义的成员必须都初始化
var s11 Student = Student{1,"mike",'m',18,"bj"}
fmt.Println("s1 = ",s11)
//指定某个成员初始化,没有指定的成员默认自动赋值为0
s22 := Student{name:"小明",addr:"bbb"}
fmt.Println(s22)
//使用里面的成员
//定义一个结构体类普通变量
var s12 Student
// 操作成员,需要使用点 < .>运算符,就跟使用java中的 response类中的参数一样
s12.id = 1
s12.addr = "北京"
s12.age = 28
s12.name = "望京soho"
s12.sex = 'm'
fmt.Println("结构体类使用s12:",s12)
//定义一个指针变量,用来保存s12的地址
var p1 *Student
p1 = &s12//取地址s12
//通过指针操作成员,p1.id 和 (*p1).id 完全等价,只能使用 . 运算符
p1.id = 1
(*p1).name = "aisi"
p1.sex = 'm'
p1.age = 18
p1.addr = "soho"
fmt.Println("p1=",p1)
//通过new来实例化结构体类
p2 := new(Student)
p2.id = 1
p2.name = "aisi"
p2.sex = 'm'
p2.age = 18
p2.addr = "soho"
fmt.Println("p2=",p2)
//结构体使用函数传参
s13 := Student{1,"mike",'m',18,"bj"}
test01(s13)
fmt.Println("s13:",s13)
//管道
}
//结构体,相当于PHP的类,在main中使用
type Student struct {
id int
name string
sex byte
age int
addr string
}
func test01(s Student){
s.id = 666
fmt.Println("test01:",s)
}
func getData() (int, int) {
return 100, 200
}
// 定义一个函数,遍历切片元素,对每个元素进行处理
func visit(list []float64, f func(float64)) {
for _, value := range list {
f(value)
}
}