Go 1.18新功能

题记

最近看到了Go 1.18的release,主要看下Go 1.18的三个新功能。

  • multi-module workspaces
  • generics
  • fuzzing
  • 20% Performance Improvements

multi-module workspaces

简而言之,允许workspace内包含其他mod的代码

$ mkdir workspace
$ cd workspace
$ mkdir hello
$ cd hello
$ go mod init example.com/hello
// coding...
$ go run example.com/hello
$ cd .. //back to workspace
$ go work init ./hello
// coding...
$ go run example.com/hello
HELLO

generics

  • 支持interface
  • 支持函数输入
package main

import "fmt"

type Number interface {
    
    
    int64 | float64 // generics type define for type int64 or float64
}

func main() {
    
    
    // Initialize a map for the integer values
    ints := map[string]int64{
    
    
        "first": 34,
        "second": 12,
    }

    // Initialize a map for the float values
    floats := map[string]float64{
    
    
        "first": 35.98,
        "second": 26.99,
    }

    fmt.Printf("Non-Generic Sums: %v and %v\n",
        SumInts(ints),
        SumFloats(floats))

    fmt.Printf("Generic Sums: %v and %v\n",
        SumIntsOrFloats[string, int64](ints),
        SumIntsOrFloats[string, float64](floats))

    fmt.Printf("Generic Sums, type parameters inferred: %v and %v\n",
        SumIntsOrFloats(ints),
        SumIntsOrFloats(floats))

    fmt.Printf("Generic Sums with Constraint: %v and %v\n",
        SumNumbers(ints),
        SumNumbers(floats))
}

// SumInts adds together the values of m.
func SumInts(m map[string]int64) int64 {
    
    
    var s int64
    for _, v := range m {
    
    
        s += v
    }
    return s
}

// SumFloats adds together the values of m.
func SumFloats(m map[string]float64) float64 {
    
    
    var s float64
    for _, v := range m {
    
    
        s += v
    }
    return s
}

// SumIntsOrFloats sums the values of map m. It supports both floats and integers
// as map values.
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
    
    
    var s V
    for _, v := range m {
    
    
        s += v
    }
    return s
}

// SumNumbers sums the values of map m. Its supports both integers
// and floats as map values.
func SumNumbers[K comparable, V Number](m map[K]V) V {
    
    
    var s V
    for _, v := range m {
    
    
        s += v
    }
    return s
}

fuzzing

通过模糊化,随机数据会在测试中运行,试图找到漏洞或导致崩溃的输入。通过模糊化可以发现的漏洞包括SQL注入、缓冲区溢出、拒绝服务和跨站点脚本攻击。
普通测试

$ go test
PASS
ok      example/fuzz  0.016s
The test now passes!

开启模糊化测试

$ go test -fuzz=Fuzz
fuzz: elapsed: 0s, gathering baseline coverage: 0/38 completed
fuzz: elapsed: 0s, gathering baseline coverage: 38/38 completed, now fuzzing with 4 workers
fuzz: elapsed: 3s, execs: 86342 (28778/sec), new interesting: 2 (total: 35)
fuzz: elapsed: 6s, execs: 193490 (35714/sec), new interesting: 4 (total: 37)
fuzz: elapsed: 9s, execs: 304390 (36961/sec), new interesting: 4 (total: 37)
...
fuzz: elapsed: 3m45s, execs: 7246222 (32357/sec), new interesting: 8 (total: 41)
^Cfuzz: elapsed: 3m48s, execs: 7335316 (31648/sec), new interesting: 8 (total: 41)
PASS
ok      example/fuzz  228.000s

只跑30s的模糊化测试

$ go test -fuzz=Fuzz -fuzztime 30s
fuzz: elapsed: 0s, gathering baseline coverage: 0/5 completed
fuzz: elapsed: 0s, gathering baseline coverage: 5/5 completed, now fuzzing with 4 workers
fuzz: elapsed: 3s, execs: 80290 (26763/sec), new interesting: 12 (total: 12)
fuzz: elapsed: 6s, execs: 210803 (43501/sec), new interesting: 14 (total: 14)
fuzz: elapsed: 9s, execs: 292882 (27360/sec), new interesting: 14 (total: 14)
fuzz: elapsed: 12s, execs: 371872 (26329/sec), new interesting: 14 (total: 14)
fuzz: elapsed: 15s, execs: 517169 (48433/sec), new interesting: 15 (total: 15)
fuzz: elapsed: 18s, execs: 663276 (48699/sec), new interesting: 15 (total: 15)
fuzz: elapsed: 21s, execs: 771698 (36143/sec), new interesting: 15 (total: 15)
fuzz: elapsed: 24s, execs: 924768 (50990/sec), new interesting: 16 (total: 16)
fuzz: elapsed: 27s, execs: 1082025 (52427/sec), new interesting: 17 (total: 17)
fuzz: elapsed: 30s, execs: 1172817 (30281/sec), new interesting: 17 (total: 17)
fuzz: elapsed: 31s, execs: 1172817 (0/sec), new interesting: 17 (total: 17)
PASS
ok      example/fuzz  31.025s

— main.go —

package main

import (
    "errors"
    "fmt"
    "unicode/utf8"
)

func main() {
    
    
    input := "The quick brown fox jumped over the lazy dog"
    rev, revErr := Reverse(input)
    doubleRev, doubleRevErr := Reverse(rev)
    fmt.Printf("original: %q\n", input)
    fmt.Printf("reversed: %q, err: %v\n", rev, revErr)
    fmt.Printf("reversed again: %q, err: %v\n", doubleRev, doubleRevErr)
}

func Reverse(s string) (string, error) {
    
    
    if !utf8.ValidString(s) {
    
    
        return s, errors.New("input is not valid UTF-8")
    }
    r := []rune(s)
    for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
    
    
        r[i], r[j] = r[j], r[i]
    }
    return string(r), nil
}

— reverse_test.go —

package main

import (
    "testing"
    "unicode/utf8"
)

func FuzzReverse(f *testing.F) {
    
    
    testcases := []string{
    
    "Hello, world", " ", "!12345"}
    for _, tc := range testcases {
    
    
        f.Add(tc) // Use f.Add to provide a seed corpus
    }
    f.Fuzz(func(t *testing.T, orig string) {
    
    
        rev, err1 := Reverse(orig)
        if err1 != nil {
    
    
            return
        }
        doubleRev, err2 := Reverse(rev)
        if err2 != nil {
    
    
            return
        }
        if orig != doubleRev {
    
    
            t.Errorf("Before: %q, after: %q", orig, doubleRev)
        }
        if utf8.ValidString(orig) && !utf8.ValidString(rev) {
    
    
            t.Errorf("Reverse produced invalid UTF-8 string %q", rev)
        }
    })
}

猜你喜欢

转载自blog.csdn.net/oe1019/article/details/124086537
go