当前位置:网站首页>【Go基础】2 - Go基本语句
【Go基础】2 - Go基本语句
2022-07-04 07:40:00 【李易安QSR】
目录
一、Go语言的数据类型
数据类型完全不能隐式转换
如:
var a int32 = 1
var b int64 = 2
a = b
- 指针类型
- 不支持指针运算
- string是值类型,其默认的初始化值为空字符串,不是nil
package main
import "testing"
func TestOne(t *testing.T) {
//指针
a := 1
aPtr := &a
t.Log(a,aPtr)
t.Logf("%T %T",a,aPtr)
//指针不允许指针运算
//aPtr += 1
var s string //默认初始化是 “”,不是nil
t.Log("*" + s + "*")
}
二、运算符
三、循环和条件
1、循环
go只支持for
package class01
import "testing"
//for循环的讲解
/* go语言中只支持for循环 */
//如何编写一个有限循环
func TestOne5_1(t *testing.T) {
n := 0
for n < 5 {
n++
t.Log(n)
}
}
//如何编写一个无限循环
func TestOne5_2(t *testing.T) {
n := 0
for {
t.Log(n)
}
//如何break呢?
//for {
// t.Log(n)
// if n == 10 {
// break
// }
// n++
//}
}
2、if
package class01
import "testing"
//如何写一个条件
func TestOne6_1(t *testing.T) {
n := 0
if n == 1 {
t.Log("n输入了1")
} else if n == 0 {
t.Log("n输入了0")
} else {
t.Log("n不知道输入了什么")
}
//与其他语言不同的地方是 条件必须是bool类型,不允许是整型或字符型,因为不存在隐式转换
/* if 1 { } */
}
- case后边默认加了有break,因此go里边不需要
- case后边可以加多个case,命中的都可以进
package class01
import "testing"
func TestOne7_1(t *testing.T) {
n := 0
switch n {
//第二种写法
//switch n := 0 n {
case 0, 1:
t.Log("memexixi")
case 2, 3, 4:
t.Log("halouhalou")
default:
t.Log("*********")
}
}
/*总结: 1、switch中可以后边跟一个赋值表达式,如函数等,再跟一个要判断的变量 2、默认每个case后边都有break,不需要再次添加 */
四、数组和切片
package class01
import "testing"
//数组的声明
func TestOne8_1(t *testing.T) {
var a [3]int
a[0] = 1 //下标也是从0开始
t.Log(a[0]) //打印刚才的赋值
t.Log(a[1]) //查看没有赋值的部分,发现并不会报错,int类型 会给出默认值0
n := 3
//t.Log(a[3]) //直接写会报错
t.Log(a[n]) //直接检查就会报错,不允许访问越界
//那字符串类型会给出什么默认值呢?
var b [3]string
t.Log(b[0]) //给出了默认值""
//数组的第二种声明方式
c := [3]int{
1, 2, 3}
t.Log(c[0])
//多维数组的声明方式
//d := [2][2]int{1, 2, 3, 4} //不允许像c中这样
d := [2][2]int{
{
1, 2}, {
3, 4}}
t.Log(d[0])
//不定数组长度的声明方式
e := [...]int{
1, 2, 3, 4, 5}
t.Log(e[3])
}
//数组的遍历
func TestOne8_2(t *testing.T) {
arr := [...]int{
1, 2, 3, 4, 5}
//传统的遍历方式
for i := 0; i < len(arr); i++ {
//{ 强制代码格式,如果写到下一行会报错,expected '{', found newline
t.Log(arr[i])
}
}
func TestOne8_3(t *testing.T) {
arr := [...]int{
1, 2, 3, 4, 5}
//range遍历
for index, item := range arr {
t.Logf("第%d个元素是%d", index, item) //格式化输入输出,跟c一样
}
//我们常常并不关注这个index的值,但是range又返回了两个,我们可以通过_进行接收
for _, item1 := range arr {
t.Log(item1)
}
}
数组内部
- 指针
- 元素个数
- 内部数组的容量
package class01
import "testing"
//数组的截取
func TestOne9_1(t *testing.T) {
//总结就是前包含,后不包含
a := [...]int{
0, 1, 2, 3, 4, 5}
t.Log(a[1:2]) //[1]
t.Log(a[1:3]) //[1 2]
t.Log(a[1:len(a)]) //[1 2 3 4 5]
t.Log(a[1:]) //不写默认为 len(a) [1 2 3 4 5]
t.Log(a[:3]) //不写默认为0 [0 1 2]
//不允许有-1,那种骚东西
//t.Log(a[0:-1])
/* 切片总结: 1、内部实现的本质是一个结构体,包含三个属性 - 数组指针ptr - 数据个数len(int) - 内部数组的容量cap (int) */
}
//如何声明一个切片呢?
func TestOne9_2(t *testing.T) {
var sl []int //这样不声明长度,就是一个切片,它就是 可变长
t.Log(len(sl), cap(sl))
sl = append(sl, 1)
t.Log(len(sl), cap(sl))
sl = append(sl, 2, 3)
t.Log(len(sl), cap(sl))
s2 := []int{
1, 2, 3, 4}
t.Log(len(s2), cap(s2))
s3 := make([]int, 3, 5)
t.Log(len(s3), cap(s3))
t.Log(s3[0], s3[1], s3[2])
//t.Log(s3[0], s3[1], s3[2], s3[3], s3[4]) //最后2个报错,告诉我们下标越界
//因此,cap表示的是整个容量,len表示当前可用的范围
}
//测试切片的增长
func TestOne9_3(t *testing.T) {
s := []int{
}
for i := 0; i < 10; i++ {
s = append(s, i)
t.Log(len(s), cap(s))
}
//Java的vector相似,容量不够的时候自动拓展,并且是x2增长
}
//切片共享内存的理解
func TestOne9_4(t *testing.T) {
arr := [10]int{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice1 := arr[:5]
slice2 := arr[3:]
t.Log(slice1)
t.Log(slice2)
//如果我修改了原始数组arr的arr[3],两个切片的内容也会跟着修改,本质上还是需要了解切片的底层实现
arr[3] = 11
t.Log(slice1)
t.Log(slice2)
}
五、Map的声明、元素访问和遍历
package class01
import (
"testing"
)
//map的声明
func TestOne10_1(t *testing.T) {
var myMap1 map[string]string //只是声明没有开辟空间
if myMap1 == nil {
t.Log("myMap1 是一个空map")
}
myMap1 = make(map[string]string, 10)
myMap1["one"] = "java"
myMap1["one1"] = "java1"
myMap1["one2"] = "java2"
myMap1["one3"] = "java3"
myMap1["one4"] = "java4"
t.Log(myMap1)
t.Log(myMap1["one3"])
//第二种方式 使用make函数进行声明
myMap2 := make(map[int]string)
myMap2[1] = "java"
myMap2[2] = "java2"
myMap2[3] = "java3"
myMap2[4] = "java4"
t.Log(myMap2)
t.Log(len(myMap2))
//第三种方式
myMap3 := map[string]string{
"one": "php",
"two": "java",
"three": "python",
}
t.Log(myMap3)
t.Logf("myMap3的长度是%d", len(myMap3))
//问:为什么map不需要初始化len?只需要cap?
}
//map常用操作
func TestOne10_2(t *testing.T) {
var myMap1 map[int]int
var myMap2 map[string]string
t.Log(myMap1[0]) //0
t.Log(myMap2["no"]) //""
//我们发现go会给我们一个map的默认值,如果不存在这个key的话,那如果我真的存了一个0或""呢?如何判断?
//其实go语言中的map取值,m[0]是返回了两个变量,第一个是value,第二个是bool,存在为true,不存在是false
if v, exist := myMap1[0]; exist {
//如果存在就打印这个值
t.Log(v)
} else {
t.Log("这个key不存在")
}
//myMap1[2] = 0
//t.Log(myMap1[2]) //会报错,因为myMap1只是声明,没有开辟控件
myMap1 = make(map[int]int)
myMap1[2] = 0
t.Log(myMap1[2])
delete(myMap1, 2) //删除操作
}
//map的遍历
func TestOne10_3(t *testing.T) {
myMap3 := map[string]string{
"one": "go",
"two": "java",
"three": "python",
}
for k, v := range myMap3 {
t.Logf("key是%s,value是%s", k, v)
}
}
package main
import "fmt"
func printMap(cityMap map[string]string) {
//map传递就是 本质也是值传递,原因是结构被复制,结构内部的指针没有变化,看起来像是引用传递
for s, s2 := range cityMap {
fmt.Println("key = ",s)
fmt.Println("value = ",s2)
}
}
func main() {
cityMap := make(map[string]string)
//添加
cityMap["china"] = "beijing"
cityMap["amaircan"] = "niuyue"
cityMap["japan"] = "tokyo"
//遍历
printMap(cityMap)
//当map中获取一个值不存在的时候,会返回默认值0
//删除
delete(cityMap,"china")
//修改
cityMap["amaircan"] = "henan"
fmt.Println("----------")
//遍历
for key, value := range cityMap {
fmt.Println("key = ",key)
fmt.Println("value = ",value)
}
}
六、在Go中实现Set集合
Go中没有Set,但是可以map[type] bool
就是用键当做存储单元,内部的值当做是否有效的标记
package class01
import "testing"
func TestOne11_1(t *testing.T) {
//go语言中没有原生支持set,是通过map的变形操作制作 使用map[type] bool
set1 := map[string]bool{
}
//新增的方式
set1["qsr"] = true
set1["wxy"] = true
//删除的方式
set1["qsr"] = false
//本质上就是通过map的key唯一来进行实现的
}
//顺带说一下,Map与工厂模式的实现
func TestOne11_2(t *testing.T) {
m := map[int]func(op int) int{
} //定义一个map,key是int,value是一个函数func,这个函数的参数是op int类型,返回值是int
m[1] = func(op int) int {
return op }
m[2] = func(op int) int {
return op * op }
m[3] = func(op int) int {
return op * op * op }
t.Log(m[1](2), m[2](2), m[3](2))
}
七、字符串
package class01
import "testing"
func TestOne12_1(t *testing.T) {
var s string
t.Log(s)
s = "hello"
t.Log(len(s))
//s[1] = '3' //go中,string是不可变的,原因是string类型的实现方式本质上是byte类型的slice
s = "\xE4\xB8\xA5" //可以存储任何二进制数据
t.Log(s)
t.Log(len(s)) //输出的是byte数,并非是简单的中文*2的长度
}
func TestOne12_2(t *testing.T) {
//对比Unicode和UTF8的区别
s1 := "中"
t.Log(len(s1))
c := []rune(s1)
t.Log(len(c))
t.Logf("中 的Unicode %x", c[0])
t.Logf("中 的UTF8 %x", s1)
/* Unicode是一种编码规则 UTF8是存储规则 */
}
//字符串的遍历
func TestOne12_3(t *testing.T) {
s := "中华人民共和国"
for _, c := range s {
t.Log(c)
t.Logf("%[1]c %[1]x %[1]d", c) // %[1] 表示都跟第一个参数对应
}
}
- 常用的字符串库
package class01
import (
"strconv"
"strings"
"testing"
)
//字符串分割 和 合并
func TestOne13_1(t *testing.T) {
s := "a:b:c"
parts := strings.Split(s, ":")
for _, ch := range parts {
t.Log(ch)
}
t.Log(strings.Join(parts, "-"))
}
//字符串类型转换
func TestOne13_2(t *testing.T) {
//将数字强制转换为string类型
s := strconv.Itoa(10)
t.Log("str:" + s) //字符串之间可以直接+
//将string类型强制转换为int
if n, err := strconv.Atoi("10"); err == nil {
t.Log(n)
}
}
八、函数
1、函数式编程
package class01
import (
"fmt"
"math/rand"
"testing"
"time"
)
//多返回值的函数
func returnMuliValues() (int, int) {
return rand.Intn(10), rand.Intn(20)
}
func TestOne14_1(t *testing.T) {
a, b := returnMuliValues()
t.Log(a, b)
a, _ = returnMuliValues()
t.Log(a)
}
//计算方法时长,装饰器的使用
func timeSpent(inner func(op int) int) func(op int) int {
//声明一个入参是函数,返回值也是一个函数的方法
return func(n int) int {
start := time.Now()
ret := inner(n) //相当于将入参中的函数放在中间执行
fmt.Println("函数执行总时间花费", time.Since(start).Seconds())
return ret
}
}
func slowFun(op int) int {
time.Sleep(time.Second * 1)
return op * 3
}
func TestOne14_2(t *testing.T) {
res := timeSpent(slowFun) //res函数,就是装饰之后的函数,返回值还是保留了原来的值,当然也可以进行改动
t.Log(res(3))
}
2、可变参数 和 defer的用法
都会转化为数组,最终通过数组遍历来实现
- defer:无论如何都会最后执行一下的
可以用作安全的释放资源,释放锁等
package class01
import (
"fmt"
"testing"
)
//可变参数的函数
func Sum(ops ...int) int {
resu := 0
for _, v := range ops {
resu += v
}
return resu
}
func TestOne15_1(t *testing.T) {
t.Log(Sum(1, 2, 3))
t.Log(Sum(1, 2, 3, 4, 5))
}
//defer的用法
func DeferDemo() {
fmt.Println("执行了defer")
}
func TestOne15_2(t *testing.T) {
defer DeferDemo()
fmt.Println("run now")
panic("e")
}
/* defer总结 1、一定会执行 2、一定是终止前执行 3、即使是panic崩溃也不会影响,类似于try catch中的finally,一定会执行 用处:安全的释放资源,释放锁等 */
边栏推荐
- Distributed transaction management DTM: the little helper behind "buy buy buy"
- Used on windows Bat file startup project
- BUUCTF(4)
- Introduction to rce in attack and defense world
- 时序数据库 InfluxDB 2.2 初探
- SQL注入测试工具之Sqli-labs下载安装重置数据库报错解决办法之一(#0{main}thrown in D:\Software\phpstudy_pro\WWW\sqli-labs-……)
- 深入浅出:了解时序数据库 InfluxDB
- tornado项目之路由装饰器
- L1-030 one gang one (15 points)
- 两年前美国芯片扭捏着不卖芯片,如今芯片堆积如山祈求中国帮忙
猜你喜欢
Two years ago, the United States was reluctant to sell chips, but now there are mountains of chips begging China for help
Distributed transaction management DTM: the little helper behind "buy buy buy"
Introduction to rce in attack and defense world
Unity 从Inspector界面打开资源管理器选择并记录文件路径
Devops Practice Guide - reading notes (long text alarm)
PCIe knowledge points -010: where to get PCIe hot plug data
Zephyr 学习笔记2,Scheduling
Write a thread pool by hand, and take you to learn the implementation principle of ThreadPoolExecutor thread pool
Xcode 14之大变化详细介绍
Adaptive spatiotemporal fusion of multi-target networks for compressed video perception enhancement
随机推荐
Devops Practice Guide - reading notes (long text alarm)
Div hidden in IE 67 shows blank problem IE 8 is normal
Enter the year, month, and determine the number of days
There is no Chinese prompt below when inputting text in win10 Microsoft Pinyin input method
在所有SwiftUI版本(1.0-4.0)中原生实现Charts图表视图之思路
Used on windows Bat file startup project
神经网络入门(下)
The IP bound to the socket is inaddr_ The meaning of any htonl (inaddr_any) (0.0.0.0 all addresses, uncertain addresses, arbitrary addresses)
Valentine's Day is coming! Without 50W bride price, my girlfriend was forcibly dragged away...
Literature collation and thesis reading methods
Unity 从Inspector界面打开资源管理器选择并记录文件路径
Mysql database - function constraint multi table query transaction
Zephyr Learning note 2, Scheduling
Activiti common operation data table relationship
L1-026 I love gplt (5 points)
Leetcode (215) -- the kth largest element in the array
Zephyr 学习笔记1,threads
[Mori city] random talk on GIS data (I)
Introduction to sap commerce cloud B2B organization function
ZABBIX monitoring system deployment