Новые функции в Go 1.18

Надпись

Недавно я увидел выпуск Go 1.18, в основном рассматривая три новые функции Go 1.18.

  • многомодульные рабочие места
  • дженерики
  • фаззинг
  • 20 % повышения производительности

многомодульные рабочие места

Короче говоря, разрешить включение кода других модов в рабочую область.

$ 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

дженерики

  • интерфейс поддержки
  • Ввод функции поддержки
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
}

фаззинг

При фаззинге случайные данные проходят через тесты, пытаясь найти ошибки или входные данные, которые вызывают сбои. Уязвимости, которые можно обнаружить с помощью фаззинга, включают внедрение 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

Нечеткий тест, который работает только в течение 30 секунд

$ 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