- Начало работы с Golang (1): Значение установки и настройки переменных окружения
- Введение в Golang (2): Изучите базовую грамматику GO за один день.
- Введение в Golang (3): изучите продвинутую грамматику GO за один день
- Начало работы с Golang (4): параллелизм
Резюме
После настройки среды это синтаксис языка для изучения. В этой статье автор надеется кратко представить различные синтаксисы Golang и провести несколько простых сравнений с C и Java, чтобы углубить память. Поскольку эта статья является лишь второй статьей для начала работы с Golang, в этой статье не будут углубляться в какие-то инструкции, а просто останется на уровне «как пользоваться», а «почему это» — речь идет о конкретных сценариях применения. и инструкции по сборке, которые автор представит в следующих статьях.
1 путеводитель
Как мы все знаем, «Hello World» — это смысл ритуала для программистов.
И эта строка «Hello World» обязательно будет включать методы, связанные с вводом и выводом. Поэтому, как импортировать пакет — это первый шаг, который нам нужно изучить.
В языке C мы используемinclude
, в Java мы используемimport
. То же самое и в Голанге, мы используемimport
Импортируйте другие пакеты. существуетпредыдущий пост, мы уже упоминали, что для импортированных пакетов компиляторGOROOT
искать вGOPATH
в поисках и, наконец, в全局GOPATH
Если вы не можете найти его, компилятор сообщит об ошибке.
Обратите внимание, что между Golang и Java есть большая разница, то есть в Golang import импортирует каталоги, а не имена пакетов. Более того, Golang не требует, чтобы имя пакета и имя каталога были согласованы.
Вот несколько примеров, иллюстрирующих взаимосвязь между именами пакетов и каталогами в Golang.Давайте сначала взглянем на структуру каталогов:
Видно, что мы
src
Ниже установлены две папки, а ниже второй папки установлены два файла go.Давайте посмотрим на код этих двух файлов,test1.goследующее:
package pktest
func Func1() {
println("这是第一个函数")
}
test2.goследующее:
package pktest
func Func2() {
println("这是第二个函数")
}
Тогда давайте посмотримtestmain.goследующее содержание:
package main
import "package1/package2"
func main() {
pktest.Func1()
}
Вы заметили, что мы звонимFunc1
Когда эта функция используется,pktest
, вместо того, что мы думаемpackage1/package2
серединаpackage2
.
Согласно нашему мышлению в Java, мы должны использоватьpackage2.Func1
вызовите метод или используйтеtest1.Func1
такой метод.
Это потому, что в ГолангеНет обязательного требования, чтобы имя пакета и имя каталога совпадали.. То есть в приведенном выше примере имя папки в нашем эталонном путиpackage2
, а для двух файлов в этой папке установлены имена пакетовpktest
. А в справочнике Голанга нам нужно заполнитьОтносительный путь, где находится исходный файл.
Другими словами, мы можем понять, что имя пакета и путь на самом деле являются двумя понятиями, и имя файла не будет явно упоминаться в Golang.Обычный формат ссылкиpackageName.FunctionName
.
вывод, как показано ниже:
-
import
Импортируется относительный путь к исходному файлу, а не имя пакета. - Принято следить за тем, чтобы имя пакета и имя каталога были согласованы, но это не обязательно (но это не рекомендуется делать, так как человек, вызывающий пакет, не сможет быстро узнать имя пакета). пакет есть)
- При ссылке на элементы внутри пакета в коде используйте имя пакета вместо имени каталога.
- Внутри папки может существовать только одно имя пакета, других ограничений на имена исходных файлов нет.
- Если в нескольких папках есть пакеты с одинаковыми именами, они на самом деле не связаны между собой.
Некоторые из вышеперечисленных выдержек изэта статья
2 Заявление
После прочтения содержимого пакета руководства давайте посмотрим, как объявить переменную. В этой части объявления переменных и в C, и в Java тоже естьбольшая разница.
2.1 Определение переменных
Сначала определим некоторые переменные:
var a int
var b float32
var c, d float64
e, f := 9, 10
var g = "Ricardo"
Мы видим, что для определения переменной в Golang нам нужно использоватьvar
ключевое слово, и в отличие от C или Java нам нужно написать тип этой переменной в имени переменнойпозже. Мало того, в Golang это позволяет нам определять несколько переменных одновременно и назначать их одновременно.
Другой способ - использовать:=
этот символ. После использования этого символа разработчикам больше не нужно писатьvar
ключевое слово, вам нужно только определить имя переменной и назначить его позже. Более того, компилятор Golang автоматически определит тип переменной на основе типа следующего за ней значения.
В процессе определения переменной, если начальное значение переменной задано во время определения, нет необходимости объявлять тип переменной, такой как переменнаяg
.
Обратите внимание, что Golang — строго типизированный язык, все переменные должны иметь типы, а переменные могут хранить данные только определенного типа.
2.2 Анонимные переменные
Переменная с идентификатором _ (подчеркивание) является анонимной переменной, зарезервированной системой, после присвоения она будет немедленно освобождена, что называется анонимной переменной. Его роль — переменная-заполнитель, присваивающая структуру своей переменной. Обычно используется при массовом назначении.
Например, функции возвращают несколько значений, нам просто нужнонекоторые из них, вам не нужно использовать _, чтобы занять место
func main() {
// 调用函数,仅仅需要第二个返回值,第一,三使用匿名变量占位
_, v, _ := getData()
fmt.Println(v)
}
// 返回两个值的函数
func getData() (int, int, int) {
// 返回3个值
return 2, 4, 8
}
Как показано в приведенном выше коде, если мне нужно только значение переменной, мне не нужно определять некоторые бессмысленные имена переменных, мне просто нужно использовать заполнители, которые являются «одноразовыми» анонимными переменными.
2.3 Константы
В определении констант Голанга используйтеconst
ключевые слова ине можетиспользовать:=
идентификатор.
3 решение
Когда мы используем Java или C, мы пишем суждения следующим образом:
if(condition){
...
}
В Golang разница только в том, что круглые скобки не требуются, но фигурные скобки по-прежнему необходимы. следующее:
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
В дополнение к тому, что не нужно писать круглые скобки, Golang также позволяет выполнить простой оператор до того, как условие будет оценено, с точкой с запятой.;
разделены.
4 цикла
В Голанге есть только один вид петли,forцикл.
Как и в суждениях, в Golang нет скобок.
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
Кроме того, в условии цикла оператор инициализации и оператор post являются необязательными, на этот раз удалите точку с запятой,for循环
это становитсяwhile循环
.
func main() {
sum := 1
for sum < 1000 {
sum += sum
}
fmt.Println(sum)
}
Мало того, что если условие цикла опущено, цикл не завершится, так что бесконечный цикл на этот раз можно записать очень компактно, иwhile(true)
Эффект тот же.
func main() {
for {
...
}
}
5 функций
5.1 Определение функций
В определении функции Голанга все функции начинаются сfunc
а именование Golang рекомендует использовать верблюжий регистр.
Обратите внимание, что в функциях Golang, если первая буква в нижнем регистре, она может использоваться только внутри пакета; если первая буква в верхнем регистре, ее можно импортировать и использовать вне пакета. Можно понять, что функция, использующая нижний регистр, является «частной», а функция, использующая верхний регистр, является «общедоступной».
В определении функции Golang она также может не принимать параметров или принимать несколько параметров. В процессе определения параметра сначала определяется имя переменной, а затем объявляется тип переменной в соответствии с форматом определения переменных. Для возвращаемого типа функции он тоже в таком формате, сначала пишем имя функции, а потом пишем возвращаемый тип:
func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
И для двух параметров одного типа может быть записан только один тип параметра, и его использование выглядит следующим образом:
func add(x, y int) int {
return x + y
}
В Golang возвращаемое значение функций отличается от C и Java.
Функции в Golang могут возвращать любое количество возвращаемых значений.
Например, следующие маленькие сливы,
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b)
}
Во-вторых, возвращаемое значение функции может быть названо:
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
Здесь мы можем понять, что эти значения переменных предопределены в верхней части функции, а пустыеreturn
Оператор по умолчанию возвращает все определенные возвращаемые переменные.
5.2defer
В Голанге есть ключевое словоdefer
.
Оператор defer откладывает выполнение функции до тех пор, пока не завершится закрывающая функция. Аргументы отложенной функции оцениваются немедленно, но функция не будет вызываться до тех пор, пока не завершится объемлющая функция.
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
В этом коде исходный путь выполнения — сверху вниз, то есть сначала выводится «мир», а затем выводится «hello». Но потому чтоdefer
Существование этого ключевого слова, эта строка оператора будет выполнена в конце, поэтому будет напечатано «привет», а затем напечатано «мир».
Обратите внимание, что за defer должен следовать оператор вызова функции, а не другие операторы, иначе компилятор сообщит об ошибке.
Сценарии, которые можно рассмотреть, — это закрытие файла или освобождение соединения с базой данных и т. д. Открытый и закрытый коды пишутся вместе, что может не только сделать код более аккуратным, но и помешать разработчикам писать длинные бизнес-коды. После этого забудьте закрыть корпус.
Что касается базовой реализации defer, то в этой статье мы не будем подробно объяснять ее. Вкратце, она помещает адрес вызова функции, следующего за оператором defer, в стек. После выполнения текущей функции ЦП выполнит следующую строку. кода вне функции.Сначала поместите адрес инструкции в стек в ЦП для выполнения, пока стек не станет пустым, затем завершите функцию и продолжите выполнение следующего кода.
Из приведенного выше оператора также можно сделать вывод, что если имеется несколько операторов refer, они будут выполняться последовательно снизу вверх.
Поскольку эта статья представляет собой лишь простое сравнение различных инструкций, подробное объяснение ссылки будет подробно объяснено в следующих статьях.
6 указатель
Для указателей, если вы разработчик C или C++, вы должны быть знакомы с ним, для разработчиков Java указатель — это что-то, что прозрачно для разработчика Объект будет занимать определенное пространство памяти в куче, а в текущей stack frame есть локальная переменная, значением которой является первый адрес этого объекта, который также является указателем.
Можно сказать, что указатель — это способ доступа разработчиков к памяти, но управление передается разработчику или виртуальной машине.
В Golang указатели используются так же, как и в C. то же самое с&
взять адрес, использовать*
Возьмите значение в адресе.
Однако, в отличие от C, в Golang нет арифметики указателей.
7 массив
В Golang массив определяется так:
var a [10]int
При этом переменная a объявляется как массив из 10 целых чисел.
Обратите внимание, что в Golang размер массивов также неизменяем, как и в C.
7.1 Нарезка
Нарезка массива, как следует из названия, заключается в вырезании массива из нужных частей по запросу.
Размер каждого массива фиксирован. Срезы, с другой стороны, обеспечивают гибкие представления элементов массива с динамическими размерами. На практике срезы используются чаще, чем массивы.
Срезы разделяются двумя нижними индексами, верхней границей и нижней границей, разделенными двоеточием:
a[low : high]
Он выбирает полуоткрытый интервал, включая первый элемент, но исключая последний элемент.
Следующее выражение создает срез, содержащий элементы a с нижними индексами от 1 до 3:
a[1:4]
Например:
func main() {
str := [4]string{
"aaa",
"bbb",
"ccc",
"ddd",
}
fmt.Println(str)
a := str[0:2]
b := str[1:3]
fmt.Println(a, b)
b[0] = "XXX"
fmt.Println(a, b)
fmt.Println(str)
}
Мы определяем массив с четырьмя элементами «aaa», «bbb», «ccc» и «ddd». Затем мы определяем два среза,a
иb
, по определению можно знать, чтоa
для «ааа» и «ббб»,b
для «bbb» и «ccc».
В это время мы изменили b[0] на «XXX», затемb
Это стало «XXX» и «ccc», в этом нет никаких сомнений. Но вопреки интуиции массив в это времяstr
, также становится "aaa", "XXX", "ccc", "ddd".
Это связано с тем, что слайс в Golang не является копией, а определяет новый указатель, указывающий на область памяти, где находится исходный массив. Следовательно, если значение нарезанного массива изменяется, значение исходного массива изменяется соответствующим образом.
Кроме того, слайсы могут быть добавлены к элементам с помощью append. Однако, если базовый массив в это время не имеет достаточной емкости, срез будет указывать на массив, который будет скопирован после перераспределения пространства.
Поэтому можно сделать вывод, что:
- Срез не хранит никаких данных, он просто описывает сегмент базового массива.
- Изменение элемента среза изменяет соответствующий элемент в его базовом массиве.
- Срезы, с которыми он разделяет базовый массив, будут отслеживать эти изменения.
7.2 make
Срезы можно создавать с помощью встроенной функции make, которая используется для создания динамических массивов.
在此之前需要解释两个定义,len(长度)和cap(容量)。
len是数组的长度,指的是这个数组在定义的时候,所约定的长度。
cap是数组的容量,指的是底层数组的长度,也可以说是原数组在内存中的长度。
在前文中所提到的切片,如果我定义了一个str[0,0]的切片,此时的长度为0,但是容量依旧还是5。
Функция make выделяет массив нулевых значений и возвращает слайс, который на него ссылается:
a := make([]int, 5) // len(a)=5
Чтобы указать его емкость, передайте третий аргумент make:
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:] // len(b)=4, cap(b)=4
То есть функция make может настроить размер среза. Говоря языком Java, его можно перегрузить.
Есть две формы, если есть только два параметра, первый параметр — тип элементов в массиве, а второй параметр — длина массива (в данном случае и длина, и емкость равны 5).
А если есть третий параметр, то третий параметр может указывать емкость массива, то есть можно указать, сколько места выделяет массив в памяти.
напиши в конце
Прежде всего, спасибо, что вы здесь.
Если эта статья сможет вам хоть немного помочь, автор будет очень рад!
Второе, на что следует обратить внимание, это то, что автор только начал контактировать с Golang. Цель написания этой статьи - сыграть эффект конспектирования. Если вы можете сравнить некоторые грамматические различия между C, Java и Golang, у вас обязательно будет много познания.ошибка. Если вы видите в этой статье что-либо, отличающееся от вашего понимания, пожалуйста, укажите на ошибку автора. Если есть какая-то часть этой статьи, которую автор не понимает достаточно, или вы не понимаете, вы также можете оставить сообщение, чтобы обменяться знаниями и вместе прогрессировать.
Тем более, что в этой статье многие места глубоко не раскопаны.Эти авторы имеют записи и планируют проанализировать эти причины с точки зрения исходного кода в последующих статьях. В этой статье, просто научившись использовать его, вы достигнете цели.
В конце еще раз спасибо~
PS: Если у вас есть другие вопросы, вы также можете найти автора на официальном аккаунте. Кроме того, все статьи будут обновлены в общедоступном аккаунте как можно скорее, добро пожаловать, чтобы поиграть с автором~