Golang进阶
如何理解并行与并发?
并行是指“并排行走”或“同时实行或实施”。 在操作系统中是指,一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的。对比地,并发是指:在同一个时间段内,两个或多个程序执行,有时间上的重叠(宏观上是同时,微观上仍是顺序执行) 。
并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
并发的实质是针对单核CPU,它的交替调度不同任务的能力
并行的实质是针对多核CPU,它指的是多个核心同时执行多个任务的能力。
因此,单核 CPU 只能并发,无法并行。并行,只存在于多核CPU的硬件条件下。 而在多核CPU中,并发并行都会同时存在,这是提高CPU处理任务能力的重要手段
Goroutine
协程,又叫做轻量级线程。这在Golang这样的编程语言中特别流行。
Go协程的特点:
- 独立的栈空间
- 共享堆空间
- 协程调度由用户控制(进程的控制是有操作系统控制,程序员不能控制)
不管是父进程创建的子进程,还是在linuxPOSIX提供的线程库。其中的管理都是交由操作系统。因此,在程序执行的过程中,总会存在执行状态的切换(用户到内核,内核到用户)。但是,golang中的协程完完全全解决了这个问题。
协程:用户态,轻量级线程。
线程:内核态,线程可以跑多个协程。
创建一个线程栈大概需要 1MB 左右,而协程栈大概只需要几 KB或者几十KB。
什么是CSP?
CSP理念: 以通信的方式来共享内存。Go 的并发哲学,依赖于 CSP 模型。
大多数编程语言,在如何实现并发的问题上,采用的都是基于线程和内存同步访问控制。而Go 的并发编程的模型则用 goroutine 和 channel 来替代。
Goroutine 和线程类似,channel 和 mutex (用于内存同步访问控制的互斥锁)类似。
Channel
make(chan+元素类型,[缓冲大小])
例如:
无缓冲通道 make(chan int)
有缓冲通道 make(chan int,2)
- channel 是一个引用类型
- channel 是线程安全的,所以用起来非常方便;channel 还提供“先进先出”的特性;它还能影响 goroutine 的阻塞和唤醒
select
- select 中只要有一个case能return,则立刻执行
- 当如果同一时间有多个case均能return则伪随机方式抽取任意一个执行
- 如果没有一个case能return则可以执行”default”块
nil究竟是什么
明确一点:nil是值而非类型。nil值只能赋值给func、slice、map、chan、interface和指针 在Go中,任何类型都会有一个初始值。
数值 类型的初始值为0,slice、map、chan、interface和指针类型的初始值为 nil, 对于nil值的变量,我们可以简化理解为初始状态变量
函数返回值命名
-
在函数有多个返回值时,只要有一个返回值有指定命名,其他的也必须有命名
-
如果返回值有有多个返回值必须加上括号
-
如果只有一个返回值并且有命名也需要加上括号
-
函数返回值名字会在函数起始处被初始化为对应类型的 零值 并且作用域为整个函数加粗样式
// defer 需要在函数结束前执行 package main
import "fmt"
func main() { println(DeferFunc1(1)) println(DeferFunc2(1)) println(DeferFunc3(1)) } func DeferFunc1(i int) (t int) { t = i defer func() { t += 3 }() return t } func DeferFunc2(i int) int { t := i t = 10 defer func() { t += 3 fmt.Println(t) }() t = 20 fmt.Println(t) return t } func DeferFunc3(i int) (t int) { defer func() { t += i }() return 2 }
//输出 4 20 23 20 3
结构体比较
- 结构体是否相同不但与属性类型个数有关,还与属性顺序相关;
- 结构体属性中有不可以比较的类型,如map,slice。可以使用reflect.DeepEqual进行比较
常量
常量不同于变量 在运行期分配内存,常量通常会被编译器在预处理节点直接展开,作为指令数据使用
const cl = 100
var bl = 123
func main() {
println(&bl, bl)
println(&cl, cl) //cannot take the address of cl
}
panic
panic 仅有最后一个可以被 recover 捕获
字符串的操作
strings包的使用
字符串的首尾字符的判断
strings.HasPrefix(s string, prefix string) bool :判断字符串s是否以prefix开头 strings.HasSuffix(s string, suffix string) bool :判断字符串s是否以suffix结尾
范例:自动在输入的url前面加上 “http://” 末尾加上 “/”
package main
import (
"fmt"
"strings"
// "strconv"
)
func main(){
var n string
fmt.Println("Input Your Web Urls:")
fmt.Scanf("%s",&n)
n=http_ch(n)
n=http_ch_end(n)
fmt.Printf("Your url is ========> [%s]",n)
}
//自动在web的URL前面添加 "http://""
func http_ch(url string) string {
if strings.HasPrefix(url,"http://"){
return url
} else {
return fmt.Sprintf("http://%s",url)
}
}
//自动在web的URL末尾添加 "/"
func http_ch_end(url string) string {
if strings.HasSuffix(url,"/"){
return url
} else {
return fmt.Sprintf("%s/",url)
}
}
其他字符串的判断
1.strings.Index(s string, str string) int 判断str在s中首次出现的位置,如果没有出现,则返回-1
2.strings.LastIndex(s string, str string) int 判断str在s中最后出现的位置,如果没有出现,则返回-1
3.strings.Replace(str string, old string, new string, n int)
4.strings.Count(str string, substr string)int 计算substr字符在字符串str中出现的次数
5.strings.Repeat(str string, count int)string 将str字符串重复count次
6.strings.ToLower(str string)string 将字符串全部转为小写
7.strings.ToUpper(str string)string 将字符串全部转为大写
去掉字符串指定字符
1.strings.TrimSpace(str string) 去掉字符串首尾空白字符(类似python的.strip()方法) 2.strings.Trim(str string, cut string) 去掉字符串首尾cut字符
3.strings.TrimLeft(str string, cut string) 去掉字符串首cut字符
4.strings.TrimRight(str string, cut string) 去掉字符串尾cut字符
字符串的切割
1.strings.Field(str string) 返回str空格分隔的所有子串的slice(类似python的.split()方法)
2.strings.Split(str string, split string) 返回str split分隔的所有子串的slice
字符串的拼接
strings.Join(s1 []string, sep string)
总结
以上就是golang进阶指南的相关介绍。
本篇也就到此结束了~感谢你的阅读