предисловие
Go (также известный как Golang)GoogleСтатически строго типизированный компилируемый язык, разработанный Робертом Гриземером, Робом Пайком и Кеном Томпсоном из . Синтаксис языка Go иCАналогично, но функционально: безопасность памяти, сборка мусора, структурная форма иCSP-styleПараллельные вычисления.
Напоминание: поскольку эта статья является более базовой, поэтому здесьПодходящееВключает: Заинтересованы в гоFront-end инженер-разработчики те, кто не знаком с языкомИнженер-разработчик JAVA. Это очень молодой язык, я надеюсь, что вы сможете понять основной игровой процесс Go из этой статьи. если ещеРазвлекайсяЭто не могло быть лучше.
Знакомство с языком Go
особенность
- Просто, быстро и безопасно
- Параллельно, интересно, с открытым исходным кодом
- Управление памятью, безопасность массива, быстрая компиляция
использовать
- серверное программирование
- Распределенные системы, агенты баз данных, промежуточное ПО
- Сетевое программирование, веб-приложение, приложение API, приложение для загрузки
- операции с базой данных
- Облачная платформа для разработки
Установка среды
Поддерживаемые системы:
- Linux
- FreeBSD
- Mac OS
- Windows
Установить на Mac
- Скачайте бинарный пакет:go1.15.darwin-amd64.tar.gz
- Разархивируйте загруженный бинарный пакет в
/usr/local
содержание
tar -C /usr/local -xzf go1.15.darwin-amd64.tar.gz
- будет
/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
части:
-
package main
Определяет имя пакета. Вы должны указать, к какому пакету принадлежит файл, в первой незакомментированной строке исходного файла, например:package main
. -
import "fmt"
Сообщите компилятору Go, что эта программа должна использоватьfmt
пакет (функций или других элементов),fmt
пакет реализует форматированиеIO
(ввод/вывод). -
func main()
это функция, с которой начинается выполнение программы. Основная функция требуется каждой исполняемой программе и, как правило, является первой функцией, которая должна выполняться после запуска (если таковая имеется).init()
функция выполнит эту функцию первой). -
fmt.Println("Hello, World!")
Строки можно выводить на консоль. - Когда идентификаторы (включая константы, переменные, типы, имена функций, поля структур и т. д.) начинаются с заглавной буквы, например:
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 предоставляет очень простой механизм обработки ошибок через встроенный интерфейс ошибок.
error
Type — тип интерфейса, вот его определение:
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 в надежде привлечь внимание других.
- Если в тексте есть ошибка, исправьте ее в комментариях.
- Если эта статья была вам полезна, ставьте лайк и поддержите ее! Спасибо за чтение.