1、面向对象
1.1 多态
在 Go 语言中,多态是通过接口来实现的:
type AnimalSounder interface {
MakeDNA()
}
func MakeSomeDNA(animalSounder AnimalSounder) { // 参数是AnimalSounder接口类型
animalSounder.MakeDNA()
}
type AnimalSounder interface {
MakeDNA()
}
func MakeSomeDNA(animalSounder AnimalSounder) {
animalSounder.MakeDNA()
}
func (c *Cat) MakeDNA() {
fmt.Println("煎鱼是煎鱼")
}
func (c *Dog) MakeDNA() {
fmt.Println("煎鱼其实不是煎鱼")
}
func main() {
MakeSomeDNA(&Cat{})
MakeSomeDNA(&Dog{})
}
1.2、什么是MVC
1. 用户通过界面(View)进行操作(比如点击按钮或输入 URL)。
2. Controller 接收用户输入,调用 Model 处理业务逻辑或数据库操作。
3. Model 返回结果,Controller 再将结果传递给 View。
4. View 根据数据渲染页面并展示给用户。
2、与其他语言对比
2.1、go语言与java有什么区别
语法和风格:
- Go语言的语法相对简洁,清晰易读,而是使用结构体和接口
- Java类和继承复杂
并发模型:
- Go语言轻量级线程和通信,并发更简单和高效。
- Java也有并发支持,但它使用线程和锁的模型,相对而言可能更复杂。
内存管理:
- Go语言具有垃圾回收机制,开发者无需手动管理内存。减少内存泄漏和提高开发效率。
- Java同样具有垃圾回收,但在某些情况下,可能需要更多的调优来处理大规模的、高性能的应用程序。
性能:
- golang比java快,
- go原生的编译性能生成的二进制文件相对较小
- java通常需要再java虚拟机JVM上运行
生态系统:
- 相对于一些其他主流语言,Go语言的第三方库数量可能相对较少。虽然Go社区在不断发展,但某些领域的库可能仍不如其他语言那样丰富。
错误处理
- 未使用到的会报错
- Go语言使用显式的错误处理机制,即通过返回值来传递错误。有时这会导致代码中充斥着处理错误的代码块,使得代码显得较为冗长。
go适合做什么
- 服务端开发
- 分布式系统,微服务
- 网络编程
- 区块链开发
- 内存KV数据库,例如boltDB、levelDB
- 云平台
3、符号类型
3.1、制表符
\t | 一个制表符 |
\r | 回车(与\n区别:从当前行最前面开始覆盖) |
3.2、格式化输出
%t | bool |
%b | 二进制 |
%o | 八进制fmt.Printf("%o\n", 255) // 输出:377 |
%O | fmt.Printf("%O\n", 255) // 输出:0o377 (Go 1.13+) |
%x | 十六进制表示,使用 a-f |
%X | 十六进制表示,使用 A-F |
%s | fmt.Printf("%s\n", "Hello, world!") // 输出:Hello, world! |
%q | fmt.Printf("%q\n", "Hello, world!") // 输出:"Hello, world!" |
%e | 科学计数法,如 -1234.456e+78 |
%E | 科学计数法,如 -1234.456E+78 |
%p | 指针地址,表示为十六进制,并加上前缀 0x |
%v | 按值的默认格式输出 |
%+v | fmt.Printf("%+v\n", struct{ X int }{X: 1}) // 输出:{X:1} |
%#v | fmt.Printf("%q\n", "Hello, world!") // 输出:"Hello, world!"/ 输出:struct { X int }{X:1} |
%T | 输出类型 |
3.3、四种声明方式
var(声明变量), const(声明常量), type(声明类型) ,func(声明函数)。
3.4、整数型
rune
处理中文、日文或者其他复合字符时,汉字3个字节
3.5、浮点
float32会出现小数后的尾数丢失
3.6、值类型
- int,float,bool,string,数组和结构体
- 变量直接存储值,内存通常在栈中分配
3.7、引用类型
- 变量存储的是一个地址,这个地址对应的空间才真正存储数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由Gc来回收。
3.8、iota
示例 :自动计数
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
使用_跳过某些值
const (
n1 = iota //0
n2 //1
_
n4 //3
)
iota
声明中间插队
const (
n1 = iota //0
n2 = 100 //100
n3 = iota //2
n4 //3
)
const n5 = iota //0
多个iota
定义在一行
const (
a, b = iota + 1, iota + 2 //1,2
c, d //2,3
e, f //3,4
)
3.9、结构体
- 结构体所有字段在内存中是连续的
-
结构体之间转换
两个结构体里字段要完全一样,赋值方式A(b)不可以a = b
package main import "fmt" type A struct { a int } type B struct { a int } func main() { var a A var b B b.a = 1 a = A(b) fmt.Println(a) }
3.11、字符串
- 字符串的内容不能在初始化后被修改,但string底层是[]byte,转成[]byte可以进行修改
转成字符串
strconv.FormatInt(int,10) strconv.Itoa(int) |
整数转为10进制字符串 |
strconv.FormatFloat(float,’f‘,10,64) | 浮点数,格式,保留小数位数10,float64 |
strconv.FormatBool(bool) | bool转string |
字符串转出
- strconv.ParseBool("true")
- strconv.ParseInt("99",10,0) 注string,10进制,第3位 0:int, 8 :int8, 16 : int16……
- strconv.ParseUint("99",10,0)
- strconv.ParseFloat("") string,大小
3.12、Go 语言中不同的类型如何比较是否相等?
- string,int,float interface 等可以通过 reflect.DeepEqual 和等于号进行比较
- slice,struct,map 使用 reflect.DeepEqual 来检测是否相等
3.13、Go中 uintptr和 unsafe.Pointer 的区别?
uintptr
用于指针和整数之间的转换,而unsafe.Pointer
则用于不同类型的指针之间的转换,它们都是不安全的操作,需要谨慎使用。
3.14、有一个很大的文件如何匹配到关键字
如果文件一般,可以用strings.contains匹配
文件很大,可以分块读取匹配
// 使用 bufio 逐行读取
scanner := bufio.NewScanner(file)
4、反射
4.1、核心
• Golang 提供了 reflect 包,主要有三个核心类型:
• reflect.Type:表示一个变量的类型。
• reflect.Value:表示一个变量的值。
• reflect.Kind:表示具体的类型分类(比如 int, struct, slice 等)。
4.2、kind和type区别
type返回[]int,kind返回更深slice
func main() {
var x []int
t := reflect.TypeOf(x)
fmt.Println("Type:", t) // 输出: Type: []int
fmt.Println("Kind:", t.Kind()) // 输出: Kind: slice
}
4.3、反射底层原理
底层主要通过 reflect
包和 runtime
包的协作完成。
-
类型信息提取:通过
runtime._type
获取类型的元数据。// reflect/type.go type rtype struct { _type *runtime._type // 指向 runtime 的类型描述符 // ... 其他反射相关的元数据 }
-
值封装:将具体值封装为
reflect.Value
,记录类型和指针。 -
动态操作:通过内存偏移和方法表实现字段访问、方法调用等。
-
安全检查:在操作前检查值的有效性(如是否可写、是否可寻址)。
4.4、用处
- 返回数据时大多数用的是json,而结构体中结构体在其他包,引用时首字母需要大写,现在就需要自定返回`json:"name"`就可以将当前字段别名化
type person struct[
Name string `json:"name"`
}
4.5、类型转换和断言的区别
-
目的:类型转换用于值的类型转换,而类型断言用于检查和获取接口值的实际类型。
-
语法:类型转换使用括号和目标类型,而类型断言使用特殊的语法
x.(T)
或x, ok := y.(T)
。 -
失败处理:类型转换可能会导致编译错误或运行时错误,而类型断言在失败时可以通过布尔值
ok
进行安全检查。
5、context
- Context 的数据结构包含 Deadline,Done,Err,Value,
- Deadline 方法返回一个 time.Time,表示当前 Context 应该结束的时间,ok 则表示有结束时间,
- Done 方法当 Context 被某一个操作进行了取消或者超时时候返回的一个 close 的 channel,告诉给 context 相关的函数要停止当前工作然后返回了,
- Err 表示 context 被取消的原因,
- Value 方法表示 context 实现共享数据存储的地方,
- 协程安全的。