Go Quick Start Guide | 🏆 Техническая проблема 2 Заявки на документы

Go
Go Quick Start Guide | 🏆 Техническая проблема 2 Заявки на документы

предисловие

Go (также известный как Golang)GoogleСтатически строго типизированный компилируемый язык, разработанный Робертом Гриземером, Робом Пайком и Кеном Томпсоном из . Синтаксис языка Go иCАналогично, но функционально: безопасность памяти, сборка мусора, структурная форма иCSP-styleПараллельные вычисления.

Напоминание: поскольку эта статья является более базовой, поэтому здесьПодходящееВключает: Заинтересованы в гоFront-end инженер-разработчики те, кто не знаком с языкомИнженер-разработчик JAVA. Это очень молодой язык, я надеюсь, что вы сможете понять основной игровой процесс Go из этой статьи. если ещеРазвлекайсяЭто не могло быть лучше.

Знакомство с языком Go

особенность

  • Просто, быстро и безопасно
  • Параллельно, интересно, с открытым исходным кодом
  • Управление памятью, безопасность массива, быстрая компиляция

использовать

  • серверное программирование
  • Распределенные системы, агенты баз данных, промежуточное ПО
  • Сетевое программирование, веб-приложение, приложение API, приложение для загрузки
  • операции с базой данных
  • Облачная платформа для разработки

Установка среды

Поддерживаемые системы:

  • Linux
  • FreeBSD
  • Mac OS
  • Windows

Установить на Mac

  1. Скачайте бинарный пакет:go1.15.darwin-amd64.tar.gz
  2. Разархивируйте загруженный бинарный пакет в/usr/localсодержание
tar -C /usr/local -xzf go1.15.darwin-amd64.tar.gz
  1. будет/usr/local/go/binДобавьте каталог в переменную окружения PATH:
export PATH=$PATH:/usr/local/go/bin

Напоминание: вы можете использовать систему MAC.pkgДважды щелкните установочный пакет в конце, чтобы завершить установку./usr/local/go/Вниз

Установка под систему Windows

Затем поговорим о платформе Windows, систему Windows можно загрузить напрямую.go1.15.windows-amd64.msiУстановите пакет для установки. (В окне установочного пакета нажмите «Далее», чтобы продолжить)

По умолчанию установочные файлы устанавливаются вC:\GoПод содержанием.

новыйtest.goфайле введите следующий пример кода:

/* test.go */
package main
import "fmt"
func main()  {
	fmt.Println("Hello, World!")
}

Вывод кода выполнения командной строки выглядит следующим образом:

Microsoft Windows [版本 10.0.18363.959]
(c) 2019 Microsoft Corporation。保留所有权利。

D:\Workspace>go run test.go
Hello, World!

структура языка

Основные компоненты языка Go:

  • декларация пакета
  • импортный пакет
  • функция
  • Переменная
  • Заявления и выражения
  • Примечания

посмотриtest.goчасти:

  1. package mainОпределяет имя пакета. Вы должны указать, к какому пакету принадлежит файл, в первой незакомментированной строке исходного файла, например:package main.
  2. import "fmt"Сообщите компилятору Go, что эта программа должна использоватьfmtпакет (функций или других элементов),fmtпакет реализует форматированиеIO(ввод/вывод).
  3. func main()это функция, с которой начинается выполнение программы. Основная функция требуется каждой исполняемой программе и, как правило, является первой функцией, которая должна выполняться после запуска (если таковая имеется).init()функция выполнит эту функцию первой).
  4. fmt.Println("Hello, World!")Строки можно выводить на консоль.
  5. Когда идентификаторы (включая константы, переменные, типы, имена функций, поля структур и т. д.) начинаются с заглавной буквы, например:Group1, то объект, использующий эту форму идентификатора, может использоваться кодом во внешнем пакете (клиентская программа должна сначала импортировать этот пакет), что называется экспортом (как в объектно-ориентированных языкахpublic); идентификаторы, начинающиеся со строчной буквы, не видны вне пакета, но они видны и доступны внутри всего пакета (как в объектно-ориентированных языкахprotected).

тип данных

тип описывать
логический Логические значения могут быть только константамиtrueилиfalse. Простой пример:var b bool = true.
Тип номера Целое числоintи плаватьfloat32,float64, язык Go поддерживает целые числа и числа с плавающей запятой, а также поддерживает сложные числа, в которых вычисление позиции осуществляется с использованием дополнения.
Тип строки Строка представляет собой последовательность символов, соединенных с символами фиксированной длины. Строки в Go объединяются отдельными байтами. Байтовое использование строк в GoUTF-8Идентификатор кодаUnicodeтекст.
производный тип В том числе: тип указателя (Pointer), тип массива, структурированный тип (struct), тип канала, тип функции, тип среза, тип интерфейса (интерфейс), тип карты

Переменная

Имена переменных языка Go состоят из букв, цифр и знаков подчеркивания, а первый символ не может быть цифрой.

Общая форма объявления переменной заключается в использованииvarключевые слова.

объявление переменной

Указывает тип переменной, если она не инициализирована, по умолчанию переменная имеет нулевое значение.

package main
import "fmt"
func main() {

    /* 声明一个变量并初始化 */
    var a = "hello"
    fmt.Println(a) /* hello */

    /* 没有初始化就为零值 */
    var b int
    fmt.Println(b) /* 0 */

    /* bool 零值为 false */
    var c bool
    fmt.Println(c) /* false */
}

Вы также можете самостоятельно определить тип переменной на основе значения.

package main
import "fmt"
func main() {
    var d = true
    fmt.Println(d) /* true */
}

Есть и другой способ объявить, опускаяvar, Уведомление:=Если в левой части не будет объявлена ​​новая переменная, произойдет ошибка компиляции Формат:

package main
import "fmt"
func main() {
    f := "hello" /* var f string = "hello" */
    fmt.Println(f)
}

Примечание: Когда тип переменной является ссылочным типом и есть операция присваивания (например:a = b), копируется только ссылка (адрес).

указатель

Переменная — это удобный заполнитель для ссылки на адрес памяти компьютера.

Адресный символ языка Go&, прежде чем поместить его в переменную, он вернет адрес памяти соответствующей переменной.

package main
import "fmt"
func main()  {
    var a int = 100  
    fmt.Printf("变量的内存地址: %x\n", &a  )
}

/* 输出 */
变量的内存地址: c000010080

что такое указатель

Переменная-указатель указывает на адрес памяти значения.

var ip *int        /* 指向整型 */
var fp *float32    /* 指向浮点型 */

Как использовать указатели

руководство:

  • определить переменную указателя
  • присвоение значения переменной-указателю
  • Доступ к значению по адресу в переменной-указателе

Перед типом указателя плюс*число (префикс), чтобы получить то, на что указывает указатель.

package main
import "fmt"
func main() {
   var a int = 10   /* 声明实际变量 */
   var ip *int        /* 声明指针变量 */

   ip = &a  /* 指针变量的存储地址 */

   fmt.Printf("a 变量的地址是: %x\n", &a  )

   /* 指针变量的存储地址 */
   fmt.Printf("ip 变量储存的指针地址: %x\n", ip )

   /* 使用指针访问值 */
   fmt.Printf("*ip 变量的值: %d\n", *ip )
}

/* 输出 */
a 变量的地址是: c000010080
ip 变量储存的指针地址: c000010080
*ip 变量的值: 10

нулевой указатель

Когда указатель определен и не назначен какой-либо переменной, его значение равноnil.

nilУказатели также известны как нулевые указатели.

nilконцептуально и на других языкахnull、None、nil、NULLТо же самое, оба относятся к нулевому значению или нулевому значению.

Переменная-указатель часто обозначается аббревиатуройptr.

структура

Массивы в Go могут хранить данные одного типа, но в структурах мы можем определять разные типы данных для разных элементов.

Структура — это набор данных, состоящий из последовательности данных одного типа или разных типов.

определить структуру

В определении структуры необходимо использоватьtypeиstructутверждение.structОператор определяет новый тип данных с одним или несколькими элементами в структуре.typeОператор задает имя структуры.

Пример:

package main
import "fmt"
type Games struct {
   name string
   url string
   class string
   game_id int
}


func main() {

    // 创建一个新的结构体
    fmt.Println(Games{"英雄联盟", "https://lol.qq.com/main.shtml", "MOBA", 666666})

    // 也可以使用 key => value 格式
    fmt.Println(Games{name: "英雄联盟", url: "https://lol.qq.com/main.shtml", class: "MOBA", game_id: 666666})

    // 忽略的字段为 0 或 空
   fmt.Println(Games{name: "英雄联盟", url: "https://lol.qq.com/main.shtml"})
}

/* 输出 */
{英雄联盟 https://lol.qq.com/main.shtml MOBA 666666}
{英雄联盟 https://lol.qq.com/main.shtml MOBA 666666}
{英雄联盟 https://lol.qq.com/main.shtml  0}

Член структуры доступа

Если вы хотите получить доступ к членам структуры, вам нужно использовать запись через точку.оператор, формат:

结构体.成员名

Пример:

package main
import "fmt"
type Games struct {
   name string
   url string
   class string
   game_id int
}

func main() {
   var LOL Games /* 声明 LOL 为 Games 类型 */

   /* LOL 描述 */
   LOL.name = "英雄联盟"
   LOL.url = "https://lol.qq.com/main.shtml"
   LOL.class = "MOBA"
   LOL.game_id = 666666

   /* 打印 LOL 信息 */
   fmt.Printf( "LOL name : %s\n", LOL.name)
   fmt.Printf( "LOL url : %s\n", LOL.url)
   fmt.Printf( "LOL class : %s\n", LOL.class)
   fmt.Printf( "LOL game_id : %d\n", LOL.game_id)
}

/* 输出 */
LOL name : 英雄联盟
LOL url : https://lol.qq.com/main.shtml
LOL class : MOBA
LOL game_id : 666666

указатель структуры

Если вы хотите изменить содержимое данных тела результата в функции, вам нужно передать указатель:

package main
import "fmt"
type Games struct {
   name string
   url string
   class string
   game_id int
}

func changeGame(game *Games) {
    game.name = "云顶之弈"
}

func main() {
    var LOL Games
    LOL.name = "英雄联盟"
   	LOL.url = "https://lol.qq.com/main.shtml"
   	LOL.class = "MOBA"
   	LOL.game_id = 666666
    changeGame(&LOL)
    fmt.Println(LOL)
}

/* 输出 */
{云顶之弈 https://lol.qq.com/main.shtml MOBA 666666}

Ломтик (ломтик)

Срез языка Go — это абстракция массива.

Длина массивов Go не может быть изменена. В некоторых сценариях такие коллекции не подходят. Go предоставляет гибкий и мощный встроенный тип слайса ("динамический массив"). По сравнению с массивами длина слайсов не фиксирована. Да , элементы могут быть присоединены, что может увеличить емкость среза при добавлении.

определить срез

/* 声明一个未指定大小的数组来定义切片 */
var identifier []type

/* 使用 make() 函数来创建切片 */
var slice1 []type = make([]type, len)
/* 简写 */
slice1 := make([]type, len)

/* 也可以指定容量,其中 capacity 为可选参数 */
make([]T, length, capacity)

здесьlen— это длина массива, а также начальная длина среза.

инициализация среза

s :=[] int {1, 2, 3} 

инициализировать срез напрямую,[]Указывает, что это тип среза,{1,2,3}Значения инициализации в свою очередь1,2,3. здесьcap=len=3

s := arr[:]

инициализировать срезs, это массивarrцитаты

s := arr[startIndex:endIndex] 

будетarrиндексstartIndexприбытьendIndex-1Элементы ниже создаются как новый фрагмент

s := arr[startIndex:] 

будетarrиндексstartIndexдо последнего элемента (по умолчаниюendIndexсостояние)

s := arr[:endIndex] 

будет представлять изarrначинается с первого элемента (по умолчаниюstartIndexслучай), чтобы подписатьendIndexэлемент под

s1 := s[startIndex:endIndex] 

нарезаяsинициализировать срезs1

s :=make([]int, len, cap) 

через встроенные функцииmake()инициализировать срезs,[]intИдентифицирует свой тип элемента какintкусок

Функции len() и cap()

Срезы индексируются и могут быть доступныlen()метод получения длины.

Срезы позволяют рассчитать емкостьcap()Вы можете измерить длину среза.

package main
import "fmt"
func main() {
   var numbers = make([]int, 3, 10)

   printSlice(numbers)
}

func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

/* 输出 */
len=3 cap=10 slice=[0 0 0]

Диапазон ( Диапазон )

на языке гоrangeключевые слова используются дляforПеребирает элементы массива (array), среза (slice), канала (channel) или коллекции (map) в цикле. В массивах и срезах возвращает индекс элемента и значение, соответствующее индексу, в коллекциях возвращаетkey-valueправильно.

package main
import "fmt"
func main() {
    /* 这是我们使用 range 去求一个 slice 的和。使用数组跟这个很类似 */
    nums := []int{1, 2, 3}
    sum := 0
    for _, num := range nums {
        sum += num
    }
    fmt.Println("sum:", sum)
    /* 在数组上使用 range 将传入 index 和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引 */
    for i, num := range nums {
        if num == 3 {
            fmt.Println("index:", i)
        }
    }
    /* range 也可以用在 map 的键值对上 */
    kvs := map[string]string{"a": "apple", "b": "banana"}
    for k, v := range kvs {
        fmt.Printf("%s -> %s\n", k, v)
    }
    /* range 也可以用来枚举 Unicode 字符串。第一个参数是字符的索引,第二个是字符(Unicode 的值)本身 */
    for i, c := range "go" {
        fmt.Println(i, c)
    }
}

/* 输出 */
sum: 6
index: 2
a -> apple
b -> banana
0 103
1 111

Карта (коллекция)

Mapпредставляет собой неупорядоченный набор пар ключ-значение.MapСамый важный момент - пройтиkeyдля быстрого получения данных,keyПодобно индексу, он указывает на значение данных.

Mapявляется коллекцией, поэтому мы можем перебирать ее, как массивы и срезы. но,Mapнеупорядочен, мы не можем определить порядок, в котором он возвращается, потому чтоMapэто использоватьhashстол для достижения.

Определить карту

Можно использовать встроенные функцииmakeтакже можно использоватьmapключевое слово для определенияMap:

/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)

Если не инициализированmap, затем создаетnil map.nil mapНельзя использовать для хранения пар ключ-значение.

Следующие примеры демонстрируют создание и использованиеmap:

package main
import "fmt"
func main() {
    var cnNameMap map[string]string /* 创建集合 */
    cnNameMap = make(map[string]string)

    /* map 插入 key-value 对,各个英文对应的中文名 */
    cnNameMap [ "Ashe" ] = "寒冰射手·艾希"
    cnNameMap [ "Annie" ] = "黑暗之女·安妮"
    cnNameMap [ "Alistar" ] = "牛头酋长·阿利斯塔"
    cnNameMap [ "Twisted" ] = "卡牌大师·崔斯特"

    /* 使用键输出中文名 */
    for cn := range cnNameMap {
        fmt.Println(cn, "中文名是", cnNameMap [cn])
    }

    /* 查看元素在集合中是否存在 */
    name, ok := cnNameMap [ "Sivir" ] /* 如果确定是真实的,则存在,否则不存在 */
    /* fmt.Println(name) */
    /* fmt.Println(ok) */
    if (ok) {
        fmt.Println("Sivir 的中文名是", name)
    } else {
        fmt.Println("Sivir 的中文名不存在")
    }
}

/* 输出 */
Annie 中文名是 黑暗之女·安妮
Alistar 中文名是 牛头酋长·阿利斯塔
Twisted 中文名是 卡牌大师·崔斯特
Ashe 中文名是 寒冰射手·艾希
Sivir 的中文名不存在

функция удаления()

delete()Функция используется для удаления элементов коллекции, параметрmapи соответствующийkey.

Примеры следующие:

package main
import "fmt"
func main() {
    /* 创建 map */
    cnNameMap := map[string]string{
    	"Annie": "黑暗之女·安妮", 
        "Alistar": "牛头酋长·阿利斯塔", 
        "Twisted": "卡牌大师·崔斯特",
        "Ashe": "寒冰射手·艾希",
    	"Sivir": "战争女神·希维尔",
    }

    fmt.Println("英雄联盟")

    /* 打印中文名 */
    for cn := range cnNameMap {
    	fmt.Println(cn, "中文名是", cnNameMap [ cn ])
    }

    /* 删除元素 */ delete(cnNameMap, "Alistar")
    fmt.Println("牛头酋长·阿利斯塔被删除")

    fmt.Println("删除元素后英雄联盟")

    /*打印中文名*/
    for cn := range cnNameMap {
    	fmt.Println(cn, "中文名是", cnNameMap [ cn ])
    }
}

/* 输出 */
英雄联盟
Annie 中文名是 黑暗之女·安妮
Alistar 中文名是 牛头酋长·阿利斯塔
Twisted 中文名是 卡牌大师·崔斯特
Ashe 中文名是 寒冰射手·艾希
Sivir 中文名是 战争女神·希维尔
牛头酋长·阿利斯塔被删除
删除元素后英雄联盟
Ashe 中文名是 寒冰射手·艾希
Sivir 中文名是 战争女神·希维尔
Annie 中文名是 黑暗之女·安妮
Twisted 中文名是 卡牌大师·崔斯特

преобразование типов

Преобразование типов используется для преобразования переменной одного типа данных в переменную другого типа. Базовый формат преобразования типа языка Go выглядит следующим образом:

类型(表达式)

Преобразование целого числа в число с плавающей запятой в следующем примере

package main
import "fmt"
func main() {
   var sum int = 10
   var count int = 3
   var mean float32
   
   mean = float32(sum)/float32(count)
   fmt.Printf("mean 的值为: %f\n",mean)
}

/* 输出 */
mean 的值为: 3.333333

интерфейс

Язык Go предоставляет другой тип данных, интерфейс, который вместе определяет все распространенные методы.Любой другой тип, реализующий эти методы, реализует интерфейс.

package main
import (
    "fmt"
)

type Phone interface {
    call()
}

type AndroidPhone struct {
}

func (androidPhone AndroidPhone) call() {
    fmt.Println("I am Android, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    var phone Phone

    phone = new(AndroidPhone)
    phone.call()

    phone = new(IPhone)
    phone.call()
}

/* 输出 */
I am Android, I can call you!
I am iPhone, I can call you!

В примере мы определяем интерфейсPhone, в интерфейсе есть методcall(). Тогда мыmainФункция определяетPhoneвведите переменные и назначьте их какAndroidPhoneиIPhone.

обработка ошибок

Язык Go предоставляет очень простой механизм обработки ошибок через встроенный интерфейс ошибок.

errorType — тип интерфейса, вот его определение:

type error interface {
    Error() string
}

Функции обычно возвращают информацию об ошибке в конечном возвращаемом значении. использоватьerrors.NewСообщение об ошибке может быть возвращено:

func Sqrt(f float64) (float64, error) {
    if f < 0 {
        return 0, errors.New("math: square root of negative number")
    }
}

Пример:

package main
import "fmt"
/* 定义一个 DivideError 结构 */
type DivideError struct {
    dividee int
    divider int
}

/* 实现 `error` 接口 */
func (de *DivideError) Error() string {
    strFormat := `
    Cannot proceed, the divider is zero.
    dividee: %d
    divider: 0
`
    return fmt.Sprintf(strFormat, de.dividee)
}

/* 定义 `int` 类型除法运算的函数 */
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
    if varDivider == 0 {
        dData := DivideError{
            dividee: varDividee,
            divider: varDivider,
        }
        errorMsg = dData.Error()
        return
    } else {
        return varDividee / varDivider, ""
    }
}

func main() {
    /* 正常情况 */
    if result, errorMsg := Divide(100, 10); errorMsg == "" {
    	fmt.Println("100/10 = ", result)
    }
    /* 当除数为零的时候会返回错误信息 */
    if _, errorMsg := Divide(100, 0); errorMsg != "" {
    	fmt.Println("errorMsg is: ", errorMsg)
    }
}

/* 输出 */
100/10 =  10
errorMsg is:
    Cannot proceed, the divider is zero.
    dividee: 100
    divider: 0

параллелизм

Язык Go поддерживает параллелизм, нам нужно только передатьgoключевое слово для включенияgoroutineВот и все.

goroutineлегкая нить,goroutineПланирование управляется средой выполнения Golang.

Например:

go f(a, b, c)

открыть новыйgoroutine:

f(a, b, c)

все в той же программеgoroutineиспользуют одно и то же адресное пространство.

package main
import (
	"fmt"
	"time"
)
func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("hi")
	say("hello")
}

/* 输出 */
hi
hello
hello
hi
hello
hi
hello
hi
hello

Справочная статья

благодарный

  • Эта статья представляет собой предварительное введение в язык Go в надежде привлечь внимание других.
  • Если в тексте есть ошибка, исправьте ее в комментариях.
  • Если эта статья была вам полезна, ставьте лайк и поддержите ее! Спасибо за чтение.

🏆 Технический спецвыпуск 2 | То, что я сделал с Go...