#492 从自学 Go 语言说起 [编辑中]
Golang 2021-02-09上一篇文章说的比较杂,这一片专门来谈一谈学习 Go 语言的一些感受吧。
coding in a complicated world
上一篇文章说的比较杂,这一片专门来谈一谈学习 Go 语言的一些感受吧。
container 包
container/heap)type Interface interface {
sort.Interface
Push(x any) // add x as element Len()
Pop() any // remove and return element Len() - 1.
}
func Fix(h Interface, i int)
func Init(h Interface)
func Pop(h Interface) any
func Push(h Interface, x any)
func Remove(h Interface, i int) any
heap.Interface:定义了操作堆的基本方法,包括获取堆中元素数量、比较元素优先级、交换元素位置、添加元素到堆中、从堆中取出元素等。heap.Init(h Interface):对一个实现了 heap.Interface 的堆进行初始化操作。heap.Push(h Interface, x interface{}):将元素 x 添加到堆 h 中。heap.Pop(h Interface) interface{}:从堆 h 中取出具有最高优先级的元素并返回。heap.Remove(h Interface, i int) interface{}:从堆 h 中移除指定索引 i 处的元素并返回。使用方法:
heap.Interface 接口的方法。heap.Init() 对堆进行初始化,或者使用 make() 创建一个空的堆。heap.Push() 将元素添加到堆中。heap.Pop() 从堆中取出具有最高优先级的元素。heap.Remove() 移除堆中的特定元素。container/heap 包提供了一种方便而高效的方式来管理具有优先级的元素。它在各种场景中都有应用,例如任务调度、事件处理、优先级队列等。通过实现自定义的 heap.Interface 接口方法,可以根据具体需求定义元素的优先级比较方式,使堆适应不同的应用场景。
container/list)type Element
func (e *Element) Next() *Element
func (e *Element) Prev() *Element
type List
func New() *List
func (l *List) Back() *Element
func (l *List) Front() *Element
func (l *List) Init() *List
func (l *List) InsertAfter(v any, mark *Element) *Element
func (l *List) InsertBefore(v any, mark *Element) *Element
func (l *List) Len() int
func (l *List) MoveAfter(e, mark *Element)
func (l *List) MoveBefore(e, mark *Element)
func (l *List) MoveToBack(e *Element)
func (l *List) MoveToFront(e *Element)
func (l *List) PushBack(v any) *Element
func (l *List) PushBackList(other *List)
func (l *List) PushFront(v any) *Element
func (l *List) PushFrontList(other *List)
func (l *List) Remove(e *Element) any
container/list 包是 Go 语言标准库中的一个包,提供了双向链表(doubly linked list)的实现。双向链表是一种数据结构,其中每个节点都包含对前一个节点和后一个节点的引用。
container/list 包提供了 List 类型,该类型代表了一个双向链表。List 类型的对象可以用来存储和操作任意类型的元素。它支持在链表的前部和后部添加和删除元素,以及在链表中搜索、遍历和修改元素。
container/list 包的主要功能和方法包括:
List 类型的方法:PushFront(v interface{}) *Element:在链表的前部插入一个值为 v 的元素,并返回该元素的指针。PushBack(v interface{}) *Element:在链表的后部插入一个值为 v 的元素,并返回该元素的指针。Remove(e *Element) interface{}:从链表中移除指定元素 e,并返回该元素的值。Front() *Element:返回链表的第一个元素。Back() *Element:返回链表的最后一个元素。Len() int:返回链表中元素的数量。Element 类型的方法:Next() *Element:返回当前元素的下一个元素。Prev() *Element:返回当前元素的前一个元素。Value() interface{}:返回当前元素的值。使用 container/list 包的步骤通常是:
container/list 包。myList := list.New()PushFront() 或 PushBack() 方法向链表中添加元素。Front() 或 Back() 方法获取链表的第一个或最后一个元素。Next() 或 Prev() 方法遍历链表中的元素。Remove() 方法从链表中移除特定的元素。container/list 包提供了一种简单而灵活的方式来管理和操作链表。它适用于需要频繁进行元素插入、删除和遍历的场景。然而,由于链表是一种指针结构,因此在随机访问和索引元素方面的性能较差。如果需要更高效的随机访问和索引操作,可以考虑使用切片(slice)或其他数据结构。
container/ring)type Ring
func New(n int) *Ring
func (r *Ring) Do(f func(any))
func (r *Ring) Len() int
func (r *Ring) Link(s *Ring) *Ring
func (r *Ring) Move(n int) *Ring
func (r *Ring) Next() *Ring
func (r *Ring) Prev() *Ring
func (r *Ring) Unlink(n int) *Ring
container/ring 包是 Go 语言标准库中的一个包,提供了环形链表(circular list)的实现。环形链表是一种特殊的链表,其中最后一个节点的下一个节点是第一个节点,形成一个环状结构。
container/ring 包提供了 Ring 类型,该类型代表了一个环形链表。Ring 类型的对象可以用来存储和操作任意类型的元素。它支持在环形链表中向前和向后遍历、插入和删除元素,以及计算环形链表的长度。
container/ring 包的主要功能和方法包括:
Ring 类型的方法:New(n int) *Ring:创建一个具有 n 个节点的新环形链表,并返回指向第一个节点的指针。Next() *Ring:返回下一个节点的指针。Prev() *Ring:返回上一个节点的指针。Move(n int) *Ring:将当前指针向前(负值)或向后(正值)移动 n 步,并返回新的指针。Link(s *Ring) *Ring:将当前环形链表连接到另一个环形链表 s 的前面,并返回连接后的环形链表。Unlink(n int) *Ring:从当前环形链表中移除下一个 n 个节点,并返回剩余的环形链表。Ring 类型的属性:Len() int:返回环形链表中节点的数量。Value() interface{}:返回当前节点的值。使用 container/ring 包的步骤通常是:
container/ring 包。New() 方法创建一个新的环形链表,并指定节点的数量。Next() 或 Prev() 方法在环形链表中遍历节点。Value() 方法获取当前节点的值。Move() 方法向前或向后移动指针。Link() 方法将两个环形链表连接起来,或使用 Unlink() 方法移除节点。container/ring 包提供了一种简单而灵活的方式来处理环形链表。它适用于需要在环形结构中进行元素遍历和操作的场景。可以使用环形链表来实现循环队列、轮转算法等应用。但是,与普通链表相比,环形链表的插入和删除操作相对较慢,因此如果需要频繁进行插入和删除操作,可能有更适合的数据结构选择。
简单地列一下 Golang 标准库中的包,知道他们是做什么的。
reflect 包通过反射(Reflection),我们可以在程序运行时,动态的增删该一些信息(类型,方法,变量),用来完成一些特殊的任务。
主要是实现不同类型都支持的一些方法。在 ORM,序列化等方面都有应用。
这种动态获取信息的能力让程序的开发变得更加灵活,但也会损失部分性能,毕竟需要进行很多类型检查、值转换等操作。
而且,滥用的话会导致程序变得复杂,可读性下降。
type Person struct {
Name string
Age int
}
func Insert(db *sql.DB, v interface{}) error {
value := reflect.ValueOf(v)
typ := reflect.TypeOf(v)
sql := "INSERT INTO persons ("
placeholders := "VALUES ("
for i := 0; i < typ.Elem().NumField(); i++ {
fieldName := typ.Elem().Field(i).Name
sql += fmt.Sprintf("%s, ", fieldName)
placeholders += "?, "
}
sql = sql[:len(sql)-2] + ")"
placeholders = placeholders[:len(placeholders)-2] + ")"
args := make([]interface{}, typ.Elem().NumField())
for i := 0; i < typ.Elem().NumField(); i++ {
args[i] = value.Elem().Field(i).Interface()
}
_, err := db.Exec(sql+placeholders, args...)
return err
}
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string
Age int
Address string
}
// 定义结构体方法
func (p Person) Hello() string {
return "Hello, " + p.Name
}
func main() {
p := Person{
Name: "Alice",
Age: 30,
Address: "123 Main St",
}
fmt.Println("获取变量的反射类型:===============")
pType := reflect.TypeOf(p) // &reflect.rtype
fmt.Printf("Type: %s, %#v\n", pType, pType) // main.Person
// fmt.Println("Type:", pType.Elem()) // panic: reflect: Elem of invalid type main.Person
pType2 := reflect.TypeOf(&p)
fmt.Printf("Type: %s, %#v\n", pType2, pType2) // *main.Person
fmt.Printf("Type: %s, %#v\n", pType2.Elem(), pType2.Elem()) // main.Person (指针类型的基础类型)
fmt.Println("获取变量的反射值:===============")
pValue := reflect.ValueOf(p) // main.Person
fmt.Printf("Value: %s, %#v\n", pValue, pValue)
pValue2 := reflect.ValueOf(&p)
fmt.Printf("Value: %s, %#v\n", pValue2, pValue2) // 地址
fmt.Printf("Value: %s, %#v\n", pValue2.Elem(), pValue2.Elem())
fmt.Println("遍历结构体字段:===============")
for i := 0; i < pType.NumField(); i++ {
field := pType.Field(i)
value := pValue.Field(i)
fmt.Printf("%s: %v\n", field.Name, value.Interface())
}
fmt.Println("修改结构体字段值:===============")
ageField1 := pValue.FieldByName("Age")
fmt.Printf("Value: %#v\n", ageField1)
// ageField1.SetInt(31) // panic: reflect: reflect.Value.SetInt using unaddressable value
// ageField1.Elem().SetInt(31) // panic: reflect: call of reflect.Value.Elem on int Value
ageField2 := pValue2.Elem().FieldByName("Age")
fmt.Printf("Value: %#v\n", ageField2)
ageField2.SetInt(31) // 只有指针类型才能通过反射修改
fmt.Println("New Age:", p.Age)
fmt.Println("调用结构体方法:===============")
helloMethod := pValue.MethodByName("Hello")
result := helloMethod.Call(nil)
fmt.Println(result)
// panic: reflect: call of reflect.Value.FieldByName on ptr Value
pValue2.FieldByName("Age")
// panic: reflect: reflect.Value.SetInt using unaddressable value
// a := reflect.Indirect(pValue)
b := reflect.Indirect(pValue2)
b.FieldByName("Age").SetInt(33)
fmt.Printf("%#v\n", b)
}
reflect.TypeOf:获取变量的类型reflect.ValueOf:获取变量的值Type.NumField:获取结构体字段数量Type.Field:获取结构体字段信息
Value.Field:获取结构体字段的值
Value.FieldByName:根据字段名获取结构体字段的值Value.SetInt:设置整数类型字段的值Value.MethodByName:根据方法名获取结构体方法Value.Call:调用结构体方法
之前讲过一次权力从何而来,今天上午又聊了一下钱莉芳的两部小说(《天意》、《天命》)
干脆再说说,我们国家古代政权的合法性问题。

最近读了钱莉芳写的几篇科幻小说。
看到日志里面有很多 tornado 的 max_clients limit reached, request queued. 日志。