Golang基础速度二十二(终结篇)
简单基础总结
package main
import (
"fmt"
"sync"
"time"
)
func main() {
/*
//字符串的一些操作
//1.获取字符串的长度
var str = "this is str"
fmt.Println(len(str))
//2.拼接字符串
var str1 = "您好"
var str2 = "huxiaobai"
fmt.Println(str1+str2)
//3.分割字符串
var str3 = "123-456-789"
split := strings.Split(str3, "-")
fmt.Println(split[0])
//4.判断字符串是否包含另一个字符串
var str4 = "this is golang"
contains := strings.Contains(str4, "golang")
fmt.Println(contains)
//5.判断字符串出现的位置
var str5 = "this is golang"
index := strings.Index(str5, "this") //从前往后 如果返回-1表示没有
fmt.Println(index)
index1 := strings.LastIndex(str5,"go") //从后往前 如果返回-1表示没有
fmt.Println(index1)
//6.拼接字符串 把切片里面的元素用*链接起来
var str6 = "123-456-789"
var arr = strings.Split(str6,"-")
var str7 = strings.Join(arr,"*")
fmt.Println(str7)
//7.修改字符串
var b1 = "big"
bytes := []byte(b1)
bytes[0]='a'
fmt.Println(string(bytes))
*/
/*
//注意:转换的时候建议从低位转换成高位 高位转换为低位的时候如果不成功就会溢出和我们想要的结果会不一样
//整形和整形之间的转换
//整形和整形之间的转换 int64位置转换为int32位
var a int64 = 16
i := int32(a)
fmt.Println(reflect.TypeOf(i)) //通过反射获取到最终的数据类型
//不同类型的整形相加 需低类型转为高类型 建议哈! 低往高了转!
var b int8 = 32
var c int16 = 30
fmt.Println(int16(b)+c)
//整形和浮点型之间的转换
//整形和浮点型运算 建议将整形转为浮点型然后再和浮点型进行运算
var e float32 = 20.23
var f int = 40
fmt.Println(e+float32(f))
*/
/*
//通过Sprintf()将不同类型转换为string类型
//sprintf的作用是将一个格式化的字符串输出到一个目的字符串中,而printf是将一个格式化的字符串输出到屏幕
//不同类型转换为string类型%后边跟着不同的符号
//int为%d float为%f bool为%t byte为%c
var g int = 20
var h float64 = 12.343
var i bool = true
var k byte = 'a'
//通过Sprintf()进行类型转换
str1 := fmt.Sprintf("%d",g) // %d表示转为十进制 用在对int类型转为string
fmt.Printf("值:%v 类型:%T\n",str1,str1)
fmt.Println("-------------------------------------------")
str2 := fmt.Sprintf("%.2f",h) // %f 表示将float类型转为string类型 %.2f表示保留两位小数
fmt.Printf("值:%v 类型:%T\n",str2,str2)
fmt.Println("-------------------------------------------")
str3 := fmt.Sprintf("%t",i)
fmt.Printf("值:%v 类型:%T\n",str3,str3) // %t 表示将布尔类型转换为string类型 最终要么true 要么false
fmt.Println("-------------------------------------------")
str4 := fmt.Sprintf("%c",k) // %c 表示将字符原样输出
fmt.Printf("值:%v 类型:%T\n",str4,str4)
fmt.Println("-------------------------------------------")
*/
/*
//通过strconv()包进行类型转换
//1.通过strconv包 把其他类型转换成string类型
var l int = 20
//strconv.FormatInt() 将int类型转为string类型 第一个参数必须是int64() 第二个参数传入int类型的进制一般都是10进制
str1 := strconv.FormatInt(int64(l), 10)
fmt.Printf("值:%v 类型:%T\n",str1,str1)
var m float32 = 12.335
//strconv.FormatFloat() 将float类型转为string类型 第一个参数必须是float64() 第二个参数传入要格式化的类型一般传f即可是一个字符 第三个参数保留的小数点但-1表示不对小数点格式化 第四个参数表示格式化的类型要么32要么64都行
str2 := strconv.FormatFloat(float64(m),'f',-1,32)
fmt.Printf("值:%v 类型:%T\n",str2,str2)
//strconv.FormatBool() 将bool类型转换为string类型 意义不大
str3 := strconv.FormatBool(true)
fmt.Printf("值:%v 类型:%T\n",str3,str3)
var n byte = 'a'
//strconv.FormatUnit() 将字符类型转为字符串 转为之后会是一个asc码跟他妈数字似的 没啥意思!
str4:=strconv.FormatUint(uint64(n),10)
fmt.Printf("值:%v 类型:%T\n",str4,str4)
//2.将string类型转为数值类型
str5 := "123456"
//先看看之前的类型和值
fmt.Printf("值:%v 类型:%T\n",str5,str5)
//strconv.ParseInt() 将字符串类型转为数值类型 第一个参数string数据 第二个参数转为10进制 第三个参数位数16 32 64
num,_ := strconv.ParseInt(str5,10,64)
fmt.Printf("值:%v 类型:%T\n",num,num)
str6 := "1234.56"
//strconv.ParseFloat()第一个参数传string数据 第二个参数传位数32 64
num1, _ := strconv.ParseFloat(str6, 32)
fmt.Printf("值:%v 类型:%T\n",num1,num1)
//3.string类型也能转为bool型但是我们不建议这么做 因为没有意义
//4.bool型和int数值类型不能相互转换
*/
/*
//时间
//1.格式化输出年月日时分秒
timeObj := time.Now()
//打印出来的时间并不是我们想要的格式
fmt.Println(timeObj)
//调取时间对象里面的方法获取年月日时分秒
year := timeObj.Year()
month := timeObj.Month()
day := timeObj.Day()
hour := timeObj.Hour()
minute := timeObj.Minute()
second := timeObj.Second()
//格式化打印输出
fmt.Printf("%d-%d-%d %d:%d:%d\n",year,month,day,hour,minute,second)
//注意: %02d 中的2表示宽度 如果整数不够2列就补上0
fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n",year,month,day,hour,minute,second)
//2.格式化输出年月日时分秒
// 2006表示年 01表示月 02表示日 03表示时(12小时制)如果03改成15则是24小时制 04表示分 05表示秒 固定写法就要是2006-01-02 03:04:05 你改一个数字就会发生时间上的错误 当然-你可以替换成别的/或者其他
//2006-01-02 03:04:05 这是golang里面格式化的模板模板模板哈
timeObj1 := time.Now()
var str6 = timeObj1.Format("2006-01-02 03:04:05") //2020-07-22 04:40:37 获取到的时间你不知道是上午还是下午
fmt.Println(str6)
//如果03改成15则是24小时制
var str7 = timeObj1.Format("2006-01-02 15:04:05") //2020-07-22 16:40:37 获取到的时间你不知道是上午还是下午
fmt.Println(str7)
//3.获取当前时间的时间戳
timeObj2 := time.Now()
unixTime := timeObj2.Unix()
fmt.Println(unixTime)
//4.将时间戳转换成日期格式
unixTime1 := 1595407628
//time.Unix()传入时间戳会返回时间对象 第一个参数必须是int64位 第二个参数是微秒数没有则传入0 返回的是Time时间类型
timeObj3 := time.Unix(int64(unixTime1),0)
str8 := timeObj3.Format("2006-01-01 03:04:05")
fmt.Println(str8)
//5.日期字符串转换成时间戳
var str9 = "2020-07-07 04:47:08"
var temp = "2006-01-02 03:04:05" //相当于模板样例 啥格式的 这个要和上边的str9的格式保持一致才行
//将日期字符串转为时间戳 time.ParseInLocation() 第一个参数模板样例 第二个参数日期字符串 第三个参数time,Local 返回的是Time类型
timeObj4, _ := time.ParseInLocation(temp, str9, time.Local)
fmt.Println(timeObj4) //打印一下日期
fmt.Println(timeObj4.Unix()) //日期调取Unix()便获取到了时间戳
//6.time包里面的常量
fmt.Println(time.Microsecond) //获取1微秒
fmt.Println(time.Millisecond) //获取1ms
fmt.Println(time.Second) //获取1s
fmt.Println(time.Minute) //获取1分钟
fmt.Println(time.Hour) //获取一小时
//7.时间操作函数
//add() 当前时间的基础上增加1小时或者1分钟或者1s......
timeObj5 := time.Now()
fmt.Println(timeObj5)
fmt.Println(timeObj5.Add(time.Hour))
//计算两个时间相差多少个小时
var starTime = "2020-08-01 00:00:00"
var endTime = "2020-08-02 00:00:00"
t1, err := time.ParseInLocation("2006-01-02 15:04:05", starTime, time.Local)
t2, err := time.ParseInLocation("2006-01-02 15:04:05", endTime, time.Local)
if err == nil && t1.Before(t2) {
diff := t2.Unix() - t1.Unix()
hour := diff/3600
fmt.Println(hour)
}else{
fmt.Println("报错")
}
//利用sub计算两个时间的差值
var st1 = "2020-07-22 00:00:00"
var st2 = "2020-07-23 00:00:00"
st11,err := time.ParseInLocation("2006-01-02 15:04:05",st1,time.Local)
st22,err := time.ParseInLocation("2006-01-02 15:04:05",st2,time.Local)
if err == nil && st11.Before(st22) {
var ret = st22.Sub(st11)
fmt.Println(ret)
}else{
fmt.Println("error")
}
//before和after的使用
var stime1 = "2020-07-22 00:00:00"
var stime2 = "2020-07-23 00:00:00"
stime11,err := time.ParseInLocation("2006-01-02 15:04:05",stime1,time.Local)
stime22,err := time.ParseInLocation("2006-01-02 15:04:05",stime2,time.Local)
//stime11是否是在stime22的前边
if stime11.Before(stime22) {
fmt.Println("yes")
}else{
fmt.Println("no")
}
//8.定时器
ticker := time.NewTicker(time.Second) //定义一个1s间隔的定时器
n :=0
//死循环里面遍历ticker里面的C 返回的是时间Time格式 比如你上边是间隔1s 那么这里就是返回的每隔1s的时间Time格式
for i := range ticker.C {
fmt.Println(i) //每秒都会执行的任务
n++
if n > 5 {
//满足条件 则需要将ticker在内存当中销毁掉
ticker.Stop()
break
}
}
fmt.Println("程序执行完毕!")
//9.第二种定时器的实现
y := 0
for {
time.Sleep(time.Second) //睡眠1s
if y > 5 {
break
}else{
fmt.Println("执行中")
}
y++
}
fmt.Println("for程序执行完毕!")
*/
/*
//float类型计算影响精度的问题 为了避免精度损失我们使用decimal包
//加法
var num1 float64 = 3.1
var num2 float64 = 4.2
d1 := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
fmt.Println(d1)
//减法
m1 := 8.9
m2 := 4.2
d2 := decimal.NewFromFloat(m1).Sub(decimal.NewFromFloat(m2))
fmt.Println(d2)
//乘法
f1 := 1.2
f2 := 3.9
f3 := decimal.NewFromFloat(f1).Mul(decimal.NewFromFloat(f2))
fmt.Println(f3)
*/
/*
//数组切片排序 sort包的使用
//正序排序
intList := []int{2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
float8List := []float64{4.2, 5.9, 12.4, 10.2, 50.7, 99.9, 31.4, 27.81828, 3.14}
stringList := []string{"a", "c", "b", "z", "x", "w", "y", "d", "f", "i"}
//对切片或者数组里面的整型进行正序排序 从小到大
sort.Ints(intList)
//对切片或者数组里面的浮点型进行正序排序 从小到大
sort.Float64s(float8List)
//对切片或者数组里面的字符串类型进行正序排序 从小到大
sort.Strings(stringList)
//打印一下看看
fmt.Println(intList)
fmt.Println(float8List)
fmt.Println(stringList)
//倒叙排序
intList1 := []int{2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
float8List1 := []float64{4.2, 5.9, 12.4, 10.2, 50.7, 99.9, 31.4, 27.81828, 3.14}
stringList1 := []string{"a", "c", "b", "z", "x", "w", "y", "d", "f", "i"}
//对切片或者数组里面的整型进行正序排序 从大到小
sort.Sort(sort.Reverse(sort.IntSlice(intList1)))
//对切片或者数组里面的浮点型进行正序排序 从大到小
sort.Sort(sort.Reverse(sort.Float64Slice(float8List1)))
//对切片或者数组里面的字符串类型进行正序排序 从大到小
sort.Sort(sort.Reverse(sort.StringSlice(stringList1)))
//打印一下
fmt.Println(intList1)
fmt.Println(float8List1)
fmt.Println(stringList1)
*/
//golang当中的并发安全和锁机制
//互斥锁案例
//for r := 0; r<20; r++{
// wg.Add(1)
// go test111()
//}
//wg.Wait()
//读写锁案例
//开启10个协程执行读操作
for i:=0;i<10;i++{
wg.Add(1)
go write()
}
//开启10个协程执行写操作
for i:=0;i<10;i++{
wg.Add(1)
go read()
}
wg.Wait()
}
// 以下是为了配合互斥锁的相关代码
var count int
var wg sync.WaitGroup
var mutex sync.Mutex
//读写锁需要使用 sync.REMutex
var mutex1 sync.RWMutex
func test111(){
//因为起来了20个协程 这20个协程之间一定会存在竞争关系 都会去改变count的值 所以容易造成错误的发生 加上了互斥锁之后 一个协程锁定了那么其他协程无法操作 只有等到当前协程解锁之后才能继续操作!
//加锁
mutex.Lock()
count++
fmt.Println("the count is :",count)
time.Sleep(time.Millisecond)
//解锁
mutex.Unlock()
wg.Done()
}
//以下是为了配合读写锁的相关代码
//写的方法
func write(){
//写锁 写的时候其他协程啥也干不了哈!
mutex1.Lock()
fmt.Println("执行写操作")
time.Sleep(time.Second * 2)
mutex1.Unlock()
wg.Done()
}
//读的方法
func read(){
//我们在这里加的是读锁 协程可以并发的读取 但是写的协程在执行的时候他是无法执行的 因为当前协程的写会阻塞其他协程的读和其他协程的写
mutex1.RLock()
fmt.Println("执行读操作")
time.Sleep(time.Second * 2)
mutex1.RUnlock()
wg.Done()
}
本作品采用《CC 协议》,转载必须注明作者和本文链接