综上所述,Go语言具有简洁易学、并发编程、高效性能、跨平台支持和高开发效率等优点。这些优点使得Go语言在不同领域的应用程序开发中变得越来越受欢迎。无论是构建Web应用程序、后端服务、分布式系统还是云原生应用程序,Go语言都是一个强大而可靠的选择。
go语言的数据类型有:1、布尔型;2、数值类型(可分为整型和浮点型);3、字符串类型;4、指针类型;5、数组类型;6、结构化类型;7、Channel类型;8、函数类型;9、切片类型;10、接口类型;11、Map类型。
基本数据类型说明:
类型 | 描述 |
---|---|
uint | 32位或64位 |
uint8 | 无符号 8 位整型 (0 到 255) |
uint16 | 无符号 16 位整型 (0 到 65535) |
uint32 | 无符号 32 位整型 (0 到 4294967295) |
uint64 | 无符号 64 位整型 (0 到 18446744073709551615) |
int | 32位或64位 |
int8 | 有符号 8 位整型 (-128 到 127) |
int16 | 有符号 16 位整型 (-32768 到 32767) |
int32 | 有符号 32 位整型 (-2147483648 到 2147483647) |
int64 | 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807) |
byte | uint8的别名(type byte = uint8) |
rune | int32的别名(type rune = int32),表示一个unicode码 |
uintptr | 无符号整型,用于存放一个指针是一种无符号的整数类型,没有指定具体的bit大小但是足以容纳指针。 uintptr类型只有在底层编程是才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方。 |
float32 | IEEE-754 32位浮点型数 |
float64 | IEEE-754 64位浮点型数 |
complex64 | 32 位实数和虚数 |
complex128 | 64 位实数和虚数 |
整型:
有符号
和无符号
两种类型。有符号: int, int8, int16, int32, int64。无符号: uint, uint8, uint16, uint32, uint64, byte浮点型:浮点型也就是小数类型,可以存放小数。比如6.6,-12.34
字符:Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存。
字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的,也就是说对于传统的字符串是由字符组成的,而Go的字符串不同,它是由字节组成的。
布尔型:
字符串:
指针:
值类型与引用类型:
Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方案。Go语言中为我们提供了很多内置包,如 fmt、os、io 等。
Golang 中的包与文件夹是一一对应的,必须创建在 GOPATH 目录下才可以被使用。Golang 中的一个包需要引用另一个包的内容,那么必须在开始使用 import 关键字进行导入才可以使用。
任何源代码文件必须属于某个包,同时源码文件的第一行有效代码必须是 package pacakgeName
语句,通过该语句声明自己所在的包。
Golang支持有符号整数、无符号整数、浮点数、布尔、字符串等类型的转换,类型转换的语法为:T(x),其中T表示要转换成的类型,x表示要转换的值。
整型类型转换:
在Go语言中整数类型包括有符号整数和无符号整数,支持转换的整数类型有int8、int16、int32、int64、uint8、uint16、uint32和uint64。其中,int8和uint8称为字节类型,int16和uint16称为短整数类型,int32和uint32称为长整数类型,int64和uint64称为长长整数类型。
整数类型的转换需要注意以下两点:
浮点型类型转换:
在Go语言中,浮点数类型包括float32和float64,支持转换的浮点数类型只能是float32和float64。浮点数类型的转换也需要注意两点:
布尔类型转换:
在Go语言中,布尔类型只有true和false两个值,支持转换的类型只有int和字符串类型。将布尔值转换成int时,true会转换成1,false转换成0。将布尔值转换成字符串时,true转换成"true",false转换成"false"。
字符串类型转换:
在Go语言中,字符串是由字符序列组成的(不可变的)数组,支持转换的类型只有原始类型。字符串转换可以通过strconv包实现。将整数转换成字符串时,可以使用 strconv.Itoa() 函数,将浮点数转换成字符串时,可以使用 strconv.FormatFloat() 函数。
在Go语言中,类型转换是一个非常重要的概念。类型转换可以将不同类型之间的值进行转换,从而满足程序的需要。但需要注意,在进行类型转换时,需要避免数据类型范围溢出和精度丢失的问题,同时需要保证转换后的类型和转换前的类型兼容。
Goroutine是Golang语言中轻量级线程的实现,可以在一个或多个线程上运行。它是由Go运行时系统管理的,是一个独立、轻量级的执行单元。与传统线程不同,goroutine运行时,它是由Go运行时系统自动进行调度,而且它的调度模型也是非常高效的,它不仅可以很好地支持高并发,而且还能够充分利用多核CPU的优势。大多数 Go 语言程序同时使用数千个 Goroutine。要创建 Goroutine,可以在函数声明之前添加 go 关键字。
停止goroutine是一个比较复杂的问题,因为goroutine在运行时没有提供显式的终止和暂停的方法。这是由于Go语言的设计目标之一就是让goroutine在运行时尽量不被阻塞,因此需要一些特殊的技巧来停止它们。
package main
import (
"fmt"
"time"
)
func worker1(stopChan chan bool) {
for {
select {
case <-stopChan:
fmt.Println("worker1 stopped")
return
default:
fmt.Println("worker1 is running")
time.Sleep(time.Second)
}
}
}
func worker2(stopChan chan bool) {
for {
select {
case <-stopChan:
fmt.Println("worker2 stopped")
return
default:
fmt.Println("worker2 is running")
time.Sleep(time.Second)
}
}
}
func main() {
stopchan := make(chan bool)
go worker1(stopchan)
go worker2(stopchan)
time.Sleep(3 * time.Second)
stopchan <- true
//stopchan <- true
time.Sleep(2 * time.Second)
}
package main
import (
"context"
"fmt"
"time"
)
func worker3(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("worker3 stopped")
return
default:
fmt.Println("worker3 is running")
time.Sleep(time.Second)
}
}
}
func worker4(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("worker4 stopped")
return
default:
fmt.Println("worker4 is running")
time.Sleep(time.Second)
}
}
}
func main() {
ctx, cancle := context.WithCancel(context.Background())
go worker3(ctx)
go worker4(ctx)
time.Sleep(3 * time.Second)
cancle()
time.Sleep(2 * time.Second)
}
package main
import (
"fmt"
"sync"
"time"
)
var wg = sync.WaitGroup{}
var stop bool
var mutex = sync.Mutex{}
func worker5() {
defer wg.Done()
for {
mutex.Lock()
if stop {
mutex.Unlock()
fmt.Println("work5 stopped")
return
}
fmt.Println("work is running")
mutex.Unlock()
time.Sleep(time.Second)
}
}
func main() {
for i := 0; i < 3; i++ {
wg.Add(1)
go worker5()
}
time.Sleep(3 * time.Second)
mutex.Lock()
stop = true
mutex.Unlock()
wg.Wait()
time.Sleep(2 * time.Second)
}
package main
import (
"fmt"
"runtime"
"time"
)
var stop bool
func work6() {
for {
if stop {
fmt.Println("work6 stopped")
return
}
fmt.Println("work6 is running")
time.Sleep(time.Second)
}
}
func main() {
go work6()
time.Sleep(3 * time.Second)
stop = true
time.Sleep(2 * time.Second)
runtime.Goexit()
}
整理了三种方法,interface{}.(type)、reflect.TypeOf(varibale)、fmt.Printf("%T\n", varibale)。详情查看下面代码。
package main
import (
"fmt"
"reflect"
)
// 方法1
func typeofObject1(variable interface{}) string {
switch variable.(type) {
case int:
return "int"
case float32:
return "float32"
case float64:
return "float64"
case bool:
return "boolean"
case string:
return "string"
default:
// 如果是结构体类型,返回结构体名称
v := reflect.ValueOf(variable)
if v.Kind() == reflect.Struct {
return v.Type().Name() + " struct{}"
}
return "unknown"
}
}
// 方法2
func typeofObject2(variable any) interface{} {
r := reflect.TypeOf(variable)
return r
}
func main() {
var num float64 = 3.14
type1 := typeofObject1(num)
type2 := typeofObject2(num)
// 方法3:
fmt.Printf("%T\n", num)
fmt.Println(type1)
fmt.Println(type2)
}
同步锁的作用是保证资源在使用时的独有性,不会因为并发而导致数据错乱,保证系统的稳定性。
无缓冲的 channel是同步的,而有缓冲的channel是非同步的。
cap函数用于获取切片、数组或通道的容量,即可以存储的元素数量的最大值。可以作用于的类型有:
new关键字是用来分配内存的函数,new(Type)作用是为T类型分配并清零一块内存,并将这块内存地址作为结果返回。也就是说new(T)会为类型为T的新项分配已置零的内存空间,并返回它的地址。在go中,返回一个指针,指针指向新分配的内存,类型为T类型的零值。
make
的作用是为slice, map or chan
的初始化 然后返回引用 make
函数是内建函数,函数定义:
func make(Type, size IntegerType) Type
make(T, args)
函数的目的和new(T)
不同 仅仅用于创建slice, map, channel
而且返回类型是实例
数组:
[3]int
和[4]int
是两种不同的数组类型切片:
make()
来初始化,初始化的时候len=cap
,然后进行扩容