GO语言学习笔记

简介: GO语言学习笔记


所谓引用类型

(reference type)特指slice、map、channel这三种预定义类型。

相比数字、数组等类型,引用类型拥有更复杂的存储结构。除分配内存外,它们还须初始化一系列属性,诸如指针、长度,甚至包括哈希分布、数据队列等。

内置函数new按指定类型长度分配零值内存,返回指针,并不关心类型内部构造和初始化方式。而引用类型则必须使用make函数创建,编译器会将make转换为目标类型专用的创建函数(或指令),以确保完成全部内存分配和相关属性初始化。

func mkslice() []int{ 
   s:=make([]int,0,10) 
   s=append(s,100) 
   return s
} 
  
func mkmap()map[string]int{ 
   m:=make(map[string]int) 
   m["a"] =1
   return m
} 
  
func main() { 
   m:=mkmap() 
   println(m["a"]) 
  
   s:=mkslice() 
   println(s[0]) 
}
```c
$go build-gcflags"-l"     // 禁用函数内联 
  
$go tool objdump-s"main\.mk"test
  
TEXT main.mkslice(SB)test.go
   CALL runtime.makeslice(SB) 
  
TEXT main.mkmap(SB)test.go
   CALL runtime.makemap(SB)
当然,new函数也可为引用类型分配内存,但这是不完整创建。以字典(map)为例,它仅分配了字典类型本身(实际就是个指针包装)所需内存,并没有分配键值存储内存,也没有初始化散列桶等内部属性,因此它无法正常工作。
```cpp
import"fmt" 
  
func main() { 
   p:=new(map[string]int)      // 函数new返回指针 
   m:= *p            
   m["a"] =1             //panic:assignment to entry in nil map(运行期错误) 
   fmt.Println(m) 
}

类型转换

隐式转换造成的问题远大于它带来的好处。

除常量、别名类型以及未命名类型外,Go强制要求使用显式类型转换。加上不支持操作符重载,所以我们总是能确定语句及表达式的明确含义。

a:=10
b:=byte(a) 
c:=a+int(b) // 混合类型表达式必须确保类型一致

同样不能将非bool类型结果当作true/false使用。

func main() { 
   x:=100
  
   var b bool=x  // 错误:cannot use x(type int)as type bool in assignment
  
   if x{      // 错误:non-bool x(type int)used as if condition
    } 
}

语法歧义

如果转换的目标是指针、单向通道或没有返回值的函数类型,那么必须使用括号,以避免造成语法分解错误。
func main() { 
   x:=100
   p:= *int(&x)    // 错误:cannot convert&x(type*int)to type int
         //       invalid indirect of int(&x) (type int) 
   println(p) 
}

正确的做法是用括号,让编译器将*int解析为指针类型。

自定义类型

使用关键字type定义用户自定义类型,包括基于现有基础类型创建,或者是结构体、函数类型等。

type flags byte
  
const( 
   read flags=1<<iota
   write
   exec
) 
  
func main() { 
   f:=read|exec
   fmt.Printf("%b\n",f)     // 输出二进制标记位 
}

和var、const类似,多个type定义可合并成组,可在函数或代码块内定义局部类型。

func main() { 
   type(              // 组 
       user struct{          // 结构体 
           name string
           age uint8
        } 
  
       event func(string)bool    // 函数类型 
    ) 
  
   u:=user{"Tom",20} 
   fmt.Println(u) 
  
   var f event=func(s string)bool{ 
       println(s) 
       return s!= "" 
    } 
  
   f("abc") 
}

即便指定了基础类型,也只表明它们有相同底层数据结构,两者间不存在任何关系,属完全不同的两种类型。除操作符外,自定义类型不会继承基础类型的其他信息(包括方法)。不能视作别名,不能隐式转换,不能直接用于比较表达式。

func main() { 
   type data int
   var d data=10
  
   var x int=d       // 错误:cannot use d(type data)as type int in assignment
   println(x) 
  
   println(d==x)      // 错误:invalid operation:d==x(mismatched types data and int) 
}

与有明确标识符的bool、int、string等类型相比,数组、切片、字典、通道等类型与具体元素类型或长度等属性有关,故称作未命名类型(unnamed type)。当然,可用type为其提供具体名称,将其改变为命名类型(named type)。

具有相同声明的未命名类型被视作同一类型。

具有相同基类型的指针。

具有相同元素类型和长度的数组(array)。

具有相同元素类型的切片(slice)。

具有相同键值类型的字典(map)。

具有相同数据类型及操作方向的通道(channel)。

具有相同字段序列(字段名、字段类型、标签,以及字段顺序)的结构体(struct)。

具有相同签名(参数和返回值列表,不包括参数名)的函数(func)。

具有相同方法集(方法名、方法签名,不包括顺序)的接口(interface)。

相关类型会在后续章节做详细说明,此处无须了解更多细节。

容易被忽视的是struct tag,它也属于类型组成部分,而不仅仅是元数据描述。

func main() { 
   var a struct{   // 匿名结构类型 
       x int   `x` 
       s string`s` 
    } 
  
   var b struct{ 
       x int
       s string
    } 
  
   b=a      // 错误:cannot use a type
               //      struct{x int"x";s string"s" }as type
               //      struct{x int;s string}in assignment
  
   fmt.Println(b) 
}
目录
相关文章
|
3天前
|
人工智能 Go 调度
掌握Go并发:Go语言并发编程深度解析
掌握Go并发:Go语言并发编程深度解析
|
19天前
|
Go
go语言中的数据类型
go语言中的数据类型
13 0
|
24天前
|
Go 开发者
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
|
24天前
|
安全 Go
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
|
24天前
|
存储 缓存 安全
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
|
6天前
|
数据采集 存储 Go
使用Go语言和chromedp库下载Instagram图片:简易指南
Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
使用Go语言和chromedp库下载Instagram图片:简易指南
|
24天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
2天前
|
Go 开发者
Golang深入浅出之-Go语言上下文(context)包:处理取消与超时
【4月更文挑战第23天】Go语言的`context`包提供`Context`接口用于处理任务取消、超时和截止日期。通过传递`Context`对象,开发者能轻松实现复杂控制流。本文解析`context`包特性,讨论常见问题和解决方案,并给出代码示例。关键点包括:1) 确保将`Context`传递给所有相关任务;2) 根据需求选择适当的`Context`创建函数;3) 定期检查`Done()`通道以响应取消请求。正确使用`context`包能提升Go程序的控制流管理效率。
7 1
|
2天前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello(&quot;Alice&quot;)`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
13 1
|
3天前
|
SQL 关系型数据库 MySQL
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程