1.Interfaces
Interfaces are named collections of method signatures.
[maxwell@oracle-db-19c Day03]$ vim interfaces.go
[maxwell@oracle-db-19c Day03]$ cat interfaces.go
package main
import (
"fmt"
"math"
)
type geometry interface {
area() float64
perim() float64
}
type rect struct {
width, height float64
}
type circle struct {
radius float64
}
func (r rect) area() float64 {
return r.width * r.height
}
func (r rect) perim() float64 {
return 2*r.width + 2*r.height
}
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}
func measure(g geometry){
fmt.Println(g)
fmt.Println(g.area())
fmt.Println(g.perim())
}
func main(){
r := rect{width: 3, height: 4}
c := circle{radius: 5}
measure(r)
measure(c)
}
[maxwell@oracle-db-19c Day03]$ go run interfaces.go
{3 4}
12
14
{5}
78.53981633974483
31.41592653589793
[maxwell@oracle-db-19c Day03
2. Struct Embedding
| Go supports embedding of structs and interfaces to express a more seamless composition of types. This is not to be confused with |
[maxwell@oracle-db-19c Day03]$ vim struct_embedding.go
[maxwell@oracle-db-19c Day03]$ cat struct_embedding.go
package main
import "fmt"
type base struct {
num int
}
func (b base) describe() string{
return fmt.Sprintf("base with num=%v", b.num)
}
type container struct {
base
str string
}
func main() {
co := container{
base: base{
num: 1,
},
str: "some name",
}
fmt.Printf("co={num: %v, str: %v}\n", co.num, co.str)
fmt.Println("also num:", co.base.num)
fmt.Println("describe:", co.describe())
type describer interface {
describe() string
}
var d describer = co
fmt.Println("describer:", d.describe())
}
[maxwell@oracle-db-19c Day03]$ go run struct_embedding.go
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1
[maxwell@oracle-db-19c Day03]$
3.Generics
Starting with version 1.18, Go has added support for generics, also known as type parameters.
[maxwell@oracle-db-19c Day03]$ vim generics.go
[maxwell@oracle-db-19c Day03]$ cat generics.go
package main
import "fmt"
func MapKeys[K comparable, V any](m map[K]V) []K{
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
type List[T any] struct {
head,tail *element[T]
}
type element[T any] struct {
next *element[T]
val T
}
func (lst *List[T]) Push(v T) {
if lst.tail == nil {
lst.head = &element[T]{val: v}
lst.tail = lst.head
} else {
lst.tail.next = &element[T]{val : v}
lst.tail = lst.tail.next
}
}
func (lst *List[T]) GetAll() []T {
var elems []T
for e := lst.head; e != nil; e = e.next {
elems = append(elems, e.val)
}
return elems
}
func main(){
var m = map[int]string{1: "2",2: "4", 4: "8"}
fmt.Println("keys:",MapKeys(m))
_= MapKeys[int, string](m)
lst := List[int]{}
lst.Push(10)
lst.Push(13)
lst.Push(23)
fmt.Println("list:", lst.GetAll())
}
[maxwell@oracle-db-19c Day03]$ go run generics.go
keys: [1 2 4]
list: [10 13 23]
[maxwell@oracle-db-19c Day03]$
4.Errors
In Go it’s idiomatic to communicate errors via an explicit, separate return value. This contrasts with the exceptions used in languages like Java and Ruby and the overloaded single result / error value sometimes used in C. Go’s approach makes it easy to see which functions return errors and to handle them using the same language constructs employed for any other, non-error tasks.
[maxwell@oracle-db-19c Day03]$ vim errors.go
[maxwell@oracle-db-19c Day03]$ cat errors.go
package main
import (
"errors"
"fmt"
)
func f1(arg int)(int, error) {
if arg == 42 {
return -1,errors.New("can't work with 42")
}
return arg + 3, nil
}
type argError struct {
arg int
prob string
}
func (e *argError) Error() string {
return fmt.Sprintf("%d - %s", e.arg, e.prob)
}
func f2(arg int)(int, error) {
if arg == 42 {
return -1, &argError{arg, "can't work with it"}
}
return arg + 3, nil
}
func main(){
for _, i := range []int{7, 42}{
if r,e := f1(i); e!= nil {
fmt.Println("f1.worked:", e)
} else {
fmt.Println("f1.worked:", r)
}
}
for _,i := range []int{7, 42} {
if r, e := f2(i); e != nil {
fmt.Println("f2 failed:",e)
} else {
fmt.Println("f2 worked:", r)
}
}
_, e := f2(42)
if ae, ok := e.(*argError); ok {
fmt.Println(ae.arg)
fmt.Println(ae.prob)
}
}
[maxwell@oracle-db-19c Day03]$ go run errors.go
f1.worked: 10
f1.worked: can't work with 42
f2 worked: 10
f2 failed: 42 - can't work with it
42
can't work with it
[maxwell@oracle-db-19c Day03]$
5.Goroutines
| A goroutine is a lightweight thread of execution. |
[maxwell@oracle-db-19c Day03]$ vim goroutines.go
[maxwell@oracle-db-19c Day03]$ cat goroutines.go
package main
import (
"fmt"
"time"
)
func f(from string){
for i := 0; i < 3; i++{
fmt.Println(from, ":", i)
}
}
func main() {
f("direct")
go f("goroutine")
go func(msg string){
fmt.Println(msg)
}("going")
time.Sleep(time.Second)
fmt.Println("done")
}
[maxwell@oracle-db-19c Day03]$ go run goroutines.go
direct : 0
direct : 1
direct : 2
going
goroutine : 0
goroutine : 1
goroutine : 2
done
[maxwell@oracle-db-19c Day03]$
本文展示了Go语言的一些关键特性,包括接口的使用,如定义几何形状的area和perim方法;结构体嵌入,允许在类型中无缝组合其他结构体或接口;从Go1.18开始引入的泛型,使得代码更通用;错误处理机制,通过显式的错误返回值进行错误管理;以及goroutines,Go的轻量级线程实现,用于并发执行任务。

被折叠的 条评论
为什么被折叠?



