Перейти - Краткое руководство

Go - это язык общего назначения, разработанный с учетом системного программирования. Первоначально он был разработан в Google в 2007 году Робертом Гриземером, Робом Пайком и Кеном Томпсоном. Он строго и статически типизирован, обеспечивает встроенную поддержку сборки мусора и поддерживает параллельное программирование.

Программы создаются с использованием пакетов для эффективного управления зависимостями. Реализации программирования Go используют традиционную модель компиляции и связывания для создания исполняемых двоичных файлов. Язык программирования Go был анонсирован в ноябре 2009 года и используется в некоторых производственных системах Google.

Особенности программирования на Go

Наиболее важные особенности программирования Go перечислены ниже -

  • Поддержка среды, использующей шаблоны, аналогичные динамическим языкам. Например, вывод типа (x: = 0 - допустимое объявление переменной x типа int)

  • Время компиляции быстрое.

  • Встроенная поддержка параллелизма: легкие процессы (через подпрограммы go), каналы, оператор выбора.

  • Программы Go просты, лаконичны и безопасны.

  • Поддержка интерфейсов и внедрения типов.

  • Создание статически связанных собственных двоичных файлов без внешних зависимостей.

Функции исключены намеренно

Чтобы язык оставался простым и лаконичным, в Go опущены следующие функции, обычно доступные на других подобных языках:

  • Поддержка наследования типов

  • Поддержка перегрузки метода или оператора

  • Поддержка циклических зависимостей между пакетами

  • Поддержка арифметики указателей

  • Поддержка утверждений

  • Поддержка общего программирования

Программы Go

Программа Go может иметь длину от 3 до миллионов строк, и ее следует записывать в один или несколько текстовых файлов с расширением «.go». Например, hello.go.

Вы можете использовать vi, vim или любой другой текстовый редактор, чтобы записать вашу программу Go в файл.

Настройка локальной среды

Если вы все еще хотите настроить свою среду для языка программирования Go, вам понадобятся следующие два программного обеспечения, доступные на вашем компьютере:

  • Текстовый редактор
  • Компилятор Go

Текстовый редактор

Для набора программ вам потребуется текстовый редактор. Примеры текстовых редакторов включают Блокнот Windows, команду редактирования ОС, Brief, Epsilon, EMACS и vim или vi.

Название и версия текстовых редакторов могут различаться в разных операционных системах. Например, Блокнот используется в Windows, а vim или vi - в Windows, а также в Linux или UNIX.

Файлы, которые вы создаете с помощью текстового редактора, называются source files. Они содержат исходный код программы. Исходные файлы для программ Go обычно имеют расширение".go".

Перед началом программирования убедитесь, что у вас есть текстовый редактор и у вас достаточно опыта, чтобы написать компьютерную программу, сохранить ее в файл, скомпилировать и, наконец, выполнить.

Компилятор Go

Исходный код, записанный в исходном файле, является удобочитаемым источником вашей программы. Его необходимо скомпилировать и превратить в машинный язык, чтобы ваш ЦП мог действительно выполнять программу в соответствии с данными инструкциями. Компилятор языка программирования Go компилирует исходный код в свою окончательную исполняемую программу.

Дистрибутив Go поставляется в виде бинарной установки для FreeBSD (выпуск 8 и выше), Linux, Mac OS X (Snow Leopard и выше) и операционных систем Windows с 32-разрядной (386) и 64-разрядной (amd64) архитектурой процессора x86.

В следующем разделе объясняется, как установить двоичный дистрибутив Go в различных ОС.

Скачать Go Archive

Загрузите последнюю версию устанавливаемого архивного файла Go из Go Downloads . В этом руководстве используется следующая версия: go1.4.windows-amd64.msi .

Он копируется в папку C: \> go.

Операционные системы Имя архива
Windows go1.4.windows-amd64.msi
Linux go1.4.linux-amd64.tar.gz
Mac go1.4.darwin-amd64-osx10.8.pkg
FreeBSD go1.4.freebsd-amd64.tar.gz

Установка в UNIX / Linux / Mac OS X и FreeBSD

Распакуйте архив для загрузки в папку / usr / local, создав дерево Go в / usr / local / go. Например -

tar -C / usr / local -xzf go1.4.linux-amd64.tar.gz

Добавьте / usr / local / go / bin в переменную среды PATH.

Операционные системы Вывод
Linux экспорт PATH = $ PATH: / usr / local / go / bin
Mac экспорт PATH = $ PATH: / usr / local / go / bin
FreeBSD экспорт PATH = $ PATH: / usr / local / go / bin

Установка в Windows

Используйте файл MSI и следуйте инструкциям по установке инструментов Go. По умолчанию установщик использует дистрибутив Go в c: \ Go. Установщик должен установить каталог c: \ Go \ bin в переменной среды Window PATH. Чтобы изменения вступили в силу, перезапустите все открытые командные запросы.

Проверка установки

Создайте файл go с именем test.go в C:\>Go_WorkSpace.

Файл: test.go

package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")
}

Теперь запустите test.go, чтобы увидеть результат -

C:\Go_WorkSpace>go run test.go

Вывод

Hello, World!

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

Пример Hello World

Программа Go в основном состоит из следующих частей:

  • Декларация пакета
  • Импортные пакеты
  • Functions
  • Variables
  • Утверждения и выражения
  • Comments

Давайте посмотрим на простой код, который будет печатать слова «Hello World» -

package main

import "fmt"

func main() {
   /* This is my first sample program. */
   fmt.Println("Hello, World!")
}

Давайте посмотрим на различные части вышеуказанной программы -

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

  • Следующая строка import «fmt» - это команда препроцессора, которая сообщает компилятору Go включить файлы, лежащие в пакете fmt.

  • Следующая строка func main () - это основная функция, с которой начинается выполнение программы.

  • Следующая строка /*...*/ игнорируется компилятором и используется для добавления комментариев в программу. Комментарии также представлены с помощью // аналогично комментариям Java или C ++.

  • Следующая строка fmt.Println (...) - это еще одна функция, доступная в Go, которая вызывает сообщение "Hello, World!" для отображения на экране. Здесь пакет fmt экспортировал метод Println, который используется для отображения сообщения на экране.

  • Обратите внимание на заглавную букву P метода Println. В языке Go имя экспортируется, если оно начинается с заглавной буквы. Экспортировано означает, что функция или переменная / константа доступны импортеру соответствующего пакета.

Выполнение программы Go

Давайте обсудим, как сохранить исходный код в файл, скомпилировать его и, наконец, выполнить программу. Пожалуйста, следуйте инструкциям ниже -

  • Откройте текстовый редактор и добавьте вышеупомянутый код.

  • Сохраните файл как hello.go

  • Откройте командную строку.

  • Перейдите в каталог, в котором вы сохранили файл.

  • Введите go run hello.go и нажмите Enter, чтобы запустить код.

  • Если в вашем коде нет ошибок, вы увидите «Hello World!» напечатаны на экране.

$ go run hello.go
Hello, World!

Убедитесь, что компилятор Go находится на вашем пути и что вы запускаете его в каталоге, содержащем исходный файл hello.go.

Мы обсудили базовую структуру программы Go в предыдущей главе. Теперь будет легко понять другие основные строительные блоки языка программирования Go.

Токены в Go

Программа Go состоит из различных токенов. Токен - это ключевое слово, идентификатор, константа, строковый литерал или символ. Например, следующий оператор Go состоит из шести токенов -

fmt.Println("Hello, World!")

Отдельные токены -

fmt
.
Println
(
   "Hello, World!"
)

Разделитель строк

В программе Go клавиша-разделитель строк является символом конца оператора. То есть для отдельных операторов не нужен специальный разделитель, например «;» в C. Компилятор Go внутренне помещает «;» как признак конца оператора, чтобы указать конец одного логического объекта.

Например, взгляните на следующие утверждения -

fmt.Println("Hello, World!")
fmt.Println("I am in Go Programming World!")

Комментарии

Комментарии в вашей программе Go похожи на вспомогательные тексты, и компилятор их игнорирует. Они начинаются с / * и заканчиваются символами * /, как показано ниже -

/* my first program in Go */

У вас не может быть комментариев внутри комментариев, и они не встречаются в строковых или символьных литералах.

Идентификаторы

Идентификатор Go - это имя, используемое для идентификации переменной, функции или любого другого определяемого пользователем элемента. Идентификатор начинается с буквы от A до Z, от a до z или символа подчеркивания _, за которым следует ноль или более букв, подчеркиваний и цифр (от 0 до 9).

идентификатор = буква {буква | unicode_digit}.

Go не допускает символов пунктуации, таких как @, $ и%, в идентификаторах. Go этоcase-sensitiveязык программирования. Таким образом, рабочая сила и рабочая сила - это два разных идентификатора в Go. Вот несколько примеров приемлемых идентификаторов -

mahesh      kumar   abc   move_name   a_123
myname50   _temp    j      a23b9      retVal

Ключевые слова

В следующем списке показаны зарезервированные слова в Go. Эти зарезервированные слова нельзя использовать в качестве имен констант, переменных или любых других идентификаторов.

сломать по умолчанию func интерфейс Выбрать
дело отложить Идти карта Struct
чан еще Идти к пакет Переключатель
const провалиться если спектр Тип
Продолжить за импорт возвращение Вар

Пробел в Go

Пробел - это термин, используемый в Go для описания пробелов, табуляции, символов новой строки и комментариев. Строка, содержащая только пробелы, возможно с комментарием, называется пустой строкой, и компилятор Go ее полностью игнорирует.

Пробелы отделяют одну часть оператора от другой и позволяют компилятору определить, где заканчивается один элемент в операторе, например int, и начинается следующий элемент. Следовательно, в следующем заявлении -

var age int;

Между int и age должен быть хотя бы один пробел (обычно пробел), чтобы компилятор мог их различить. С другой стороны, в следующем заявлении -

fruit = apples + oranges;   // get the total fruit

Пробелы между фруктами и = или между = и яблоками не требуются, хотя вы можете включить некоторые из них, если хотите для удобства чтения.

В языке программирования Go типы данных относятся к обширной системе, используемой для объявления переменных или функций различных типов. Тип переменной определяет, сколько места она занимает в хранилище и как интерпретируется сохраненный битовый шаблон.

Типы в Go можно классифицировать следующим образом:

Sr.No. Типы и описание
1

Boolean types

Они являются логическими типами и состоят из двух предопределенных констант: (а) истина (б) ложь.

2

Numeric types

Это снова арифметические типы, и они представляют а) целые типы или б) значения с плавающей запятой во всей программе.

3

String types

Тип строки представляет собой набор строковых значений. Его значение представляет собой последовательность байтов. Строки - это неизменяемые типы, которые после создания невозможно изменить содержимое строки. Предварительно объявленный тип строки - строка.

4

Derived types

Они включают (a) типы указателей, (b) типы массивов, (c) типы структур, (d) типы объединения и (e) типы функций f) типы срезов g) типы интерфейсов h) типы карт i) типы каналов

Типы массивов и структурные типы вместе называются aggregate types. Тип функции определяет набор всех функций с одинаковыми параметрами и типами результатов. Мы обсудим основные типы в следующем разделе, а другие типы будут рассмотрены в следующих главах.

Целочисленные типы

Предопределенные архитектурно-независимые целочисленные типы:

Sr.No. Типы и описание
1

uint8

8-битные целые числа без знака (от 0 до 255)

2

uint16

16-разрядные целые числа без знака (от 0 до 65535)

3

uint32

32-битные целые числа без знака (от 0 до 4294967295)

4

uint64

64-битные целые числа без знака (от 0 до 18446744073709551615)

5

int8

8-битные целые числа со знаком (от -128 до 127)

6

int16

16-разрядные целые числа со знаком (от -32768 до 32767)

7

int32

32-разрядные целые числа со знаком (от -2147483648 до 2147483647)

8

int64

64-битные целые числа со знаком (от -9223372036854775808 до 9223372036854775807)

Плавающие типы

Предопределенные архитектурно-независимые типы с плавающей запятой:

Sr.No. Типы и описание
1

float32

IEEE-754 32-битные числа с плавающей запятой

2

float64

IEEE-754 64-битные числа с плавающей запятой

3

complex64

Комплексные числа с вещественными и мнимыми частями типа float32

4

complex128

Комплексные числа с вещественными и мнимыми частями типа float64

Значение n-битового целого числа равно n битам и представлено с использованием арифметических операций с дополнением до двух.

Другие числовые типы

Существует также набор числовых типов с размерами, зависящими от реализации -

Sr.No. Типы и описание
1

byte

то же, что и uint8

2

rune

то же, что и int32

3

uint

32 или 64 бит

4

int

того же размера, что и uint

5

uintptr

целое число без знака для хранения неинтерпретированных битов значения указателя

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

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

Старший Нет Тип и описание
1

byte

Обычно один октет (один байт). Это байтовый тип.

2

int

Самый естественный размер целого числа для машины.

3

float32

Значение с плавающей запятой одинарной точности.

Язык программирования Go также позволяет определять различные другие типы переменных, такие как Enumeration, Pointer, Array, Structure и Union, которые мы обсудим в следующих главах. В этой главе мы сосредоточимся только на основных типах переменных.

Определение переменной в Go

Определение переменной сообщает компилятору, где и сколько памяти создать для переменной. Определение переменной указывает тип данных и содержит список из одной или нескольких переменных этого типа следующим образом:

var variable_list optional_data_type;

Вот, optional_data_type является допустимым типом данных Go, включая byte, int, float32, complex64, boolean или любой пользовательский объект и т. д., и variable_listможет состоять из одного или нескольких имен идентификаторов, разделенных запятыми. Здесь показаны некоторые действительные декларации -

var  i, j, k int;
var  c, ch byte;
var  f, salary float32;
d =  42;

Заявление “var i, j, k;”объявляет и определяет переменные i, j и k; который инструктирует компилятор создать переменные с именами i, j и k типа int.

Переменные можно инициализировать (присвоить начальное значение) в их объявлении. Тип переменной автоматически определяется компилятором на основе переданного ему значения. Инициализатор состоит из знака равенства, за которым следует постоянное выражение:

variable_name = value;

Например,

d = 3, f = 5;    // declaration of d and f. Here d and f are int

Для определения без инициализатора: переменные со статической продолжительностью хранения неявно инициализируются значением nil (все байты имеют значение 0); начальное значение всех остальных переменных - нулевое значение их типа данных.

Объявление статического типа в Go

Объявление переменной статического типа обеспечивает компилятору гарантию того, что существует одна доступная переменная с данным типом и именем, так что компилятор может продолжить компиляцию, не требуя полной информации о переменной. Объявление переменной имеет смысл только во время компиляции, компилятору требуется фактическое объявление переменной во время связывания программы.

пример

Попробуйте следующий пример, где переменная была объявлена ​​с типом и инициализирована внутри основной функции:

package main

import "fmt"

func main() {
   var x float64
   x = 20.0
   fmt.Println(x)
   fmt.Printf("x is of type %T\n", x)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

20
x is of type float64

Объявление динамического типа / вывод типа в Go

Объявление переменной динамического типа требует, чтобы компилятор интерпретировал тип переменной на основе переданного ему значения. Компилятор не требует, чтобы переменная имела статический тип как необходимое требование.

пример

Попробуйте следующий пример, в котором переменные были объявлены без какого-либо типа. Обратите внимание: в случае вывода типа мы инициализировали переменнуюy с оператором: =, тогда как x инициализируется с помощью оператора =.

package main

import "fmt"

func main() {
   var x float64 = 20.0

   y := 42 
   fmt.Println(x)
   fmt.Println(y)
   fmt.Printf("x is of type %T\n", x)
   fmt.Printf("y is of type %T\n", y)	
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

20
42
x is of type float64
y is of type int

Объявление смешанных переменных в Go

Переменные разных типов могут быть объявлены за один раз, используя вывод типа.

пример

package main

import "fmt"

func main() {
   var a, b, c = 3, 4, "foo"  
	
   fmt.Println(a)
   fmt.Println(b)
   fmt.Println(c)
   fmt.Printf("a is of type %T\n", a)
   fmt.Printf("b is of type %T\n", b)
   fmt.Printf("c is of type %T\n", c)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

3
4
foo
a is of type int
b is of type int
c is of type string

Lvalues ​​и rvalues ​​в Go

В Go есть два вида выражений:

  • lvalue- Выражение, относящееся к области памяти, называется выражением «lvalue». Lvalue может отображаться как левая или правая часть присваивания.

  • rvalue- Термин rvalue относится к значению данных, которое хранится по некоторому адресу в памяти. Rvalue - это выражение, которому не может быть присвоено значение, что означает, что rvalue может появляться справа, но не слева от присваивания.

Переменные - это lvalue, поэтому они могут появляться в левой части присваивания. Числовые литералы являются r-значениями, поэтому не могут быть присвоены и не могут отображаться с левой стороны.

Следующее утверждение действительно -

x = 20.0

Следующее утверждение недействительно. Это вызовет ошибку времени компиляции -

10 = 20

Константы относятся к фиксированным значениям, которые программа не может изменять во время выполнения. Эти фиксированные значения также называютсяliterals.

Константы могут иметь любой из основных типов данных, например целочисленную константу, константу с плавающей запятой, символьную константу или строковый литерал . Также есть константы перечисления.

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

Целочисленные литералы

Целочисленный литерал может быть десятичной, восьмеричной или шестнадцатеричной константой. Префикс определяет основание или основание системы счисления: 0x или 0X для шестнадцатеричного числа, 0 для восьмеричного и ничего для десятичного.

Целочисленный литерал также может иметь суффикс, который представляет собой комбинацию U и L для unsigned и long соответственно. Суффикс может быть в верхнем или нижнем регистре и может быть в любом порядке.

Вот несколько примеров целочисленных литералов -

212         /* Legal */
215u        /* Legal */
0xFeeL      /* Legal */
078         /* Illegal: 8 is not an octal digit */
032UU       /* Illegal: cannot repeat a suffix */

Ниже приведены другие примеры различных типов целочисленных литералов.

85         /* decimal */
0213       /* octal */
0x4b       /* hexadecimal */
30         /* int */
30u        /* unsigned int */
30l        /* long */
30ul       /* unsigned long */

Литералы с плавающей точкой

Литерал с плавающей запятой состоит из целой части, десятичной точки, дробной части и экспоненты. Вы можете представлять литералы с плавающей запятой в десятичной или экспоненциальной форме.

При представлении с использованием десятичной формы вы должны включать десятичную точку, показатель степени или и то, и другое, а при представлении с использованием экспоненциальной формы вы должны включать целую часть, дробную часть или и то, и другое. Знаковая экспонента вводится буквами e или E.

Вот несколько примеров литералов с плавающей запятой -

3.14159       /* Legal */
314159E-5L    /* Legal */
510E          /* Illegal: incomplete exponent */
210f          /* Illegal: no decimal or exponent */
.e55          /* Illegal: missing integer or fraction */

Последовательность побега

Если перед некоторыми символами стоит обратная косая черта, они будут иметь особое значение в Go. Они известны как коды Escape Sequence, которые используются для представления новой строки (\ n), табуляции (\ t), backspace и т. Д. Здесь у вас есть список некоторых из таких кодов escape-последовательностей -

Последовательность выхода Имея в виду
\\ \ персонаж
\ ' ' персонаж
\ " " персонаж
\? ? персонаж
\ а Оповещение или звонок
\ b Backspace
\ f Подача формы
\ п Новая линия
Возврат каретки
\ т Горизонтальная вкладка
\ v Вертикальная табуляция
\ ооо Восьмеричное число от одной до трех цифр
\ ххх. . . Шестнадцатеричное число из одной или нескольких цифр

В следующем примере показано, как использовать \t в программе -

package main

import "fmt"

func main() {
   fmt.Printf("Hello\tWorld!")
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Hello World!

Строковые литералы в Go

Строковые литералы или константы заключаются в двойные кавычки "". Строка содержит символы, похожие на символьные литералы: простые символы, escape-последовательности и универсальные символы.

Вы можете разбить длинную строку на несколько строк, используя строковые литералы и разделяя их пробелами.

Вот несколько примеров строковых литералов. Все три формы - идентичные струны.

"hello, dear"

"hello, \

dear"

"hello, " "d" "ear"

Const Ключевое слово

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

const variable type = value;

В следующем примере показано, как использовать const ключевое слово -

package main

import "fmt"

func main() {
   const LENGTH int = 10
   const WIDTH int = 5   
   var area int

   area = LENGTH * WIDTH
   fmt.Printf("value of area : %d", area)   
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

value of area : 50

Обратите внимание, что определение констант ЗАГЛАВНЫМИ буквами является хорошей практикой программирования.

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

  • Арифметические операторы
  • Операторы отношения
  • Логические операторы
  • Побитовые операторы
  • Операторы присваивания
  • Разные операторы

В этом руководстве поочередно объясняются арифметические, реляционные, логические, побитовые, присваивающие и другие операторы.

Арифметические операторы

В следующей таблице показаны все арифметические операторы, поддерживаемые языком Go. Предположим переменнуюA содержит 10 и переменную B держит 20, тогда -

Показать примеры

Оператор Описание пример
+ Добавляет два операнда A + B дает 30
- Вычитает второй операнд из первого A - B дает -10
* Умножает оба операнда A * B дает 200
/ Делит числитель на знаменатель. Б / А дает 2
% Оператор модуля; дает остаток после целочисленного деления. B% A дает 0
++ Оператор инкремента. Увеличивает целое значение на единицу. А ++ дает 11
- Оператор декремента. Уменьшает целочисленное значение на единицу. A-- дает 9

Операторы отношения

В следующей таблице перечислены все операторы отношения, поддерживаемые языком Go. Предположим переменнуюA содержит 10 и переменную B держит 20, то -

Показать примеры

Оператор Описание пример
== Он проверяет, равны ли значения двух операндов; если да, условие становится верным. (A == B) неверно.
знак равно Он проверяет, равны ли значения двух операндов; если значения не равны, то условие выполняется. (A! = B) верно.
> Он проверяет, больше ли значение левого операнда, чем значение правого операнда; если да, условие становится верным. (A> B) неверно.
< Он проверяет, меньше ли значение левого операнда, чем значение правого операнда; если да, условие становится верным. (A <B) верно.
> = Он проверяет, больше ли значение левого операнда, чем или равно значению правого операнда; если да, условие становится верным. (A> = B) неверно.
<= Он проверяет, меньше ли значение левого операнда или равно значению правого операнда; если да, условие становится верным. (A <= B) верно.

Логические операторы

В следующей таблице перечислены все логические операторы, поддерживаемые языком Go. Предположим переменнуюA содержит 1 и переменную B имеет 0, то -

Показать примеры

Оператор Описание пример
&& Вызывается логическим оператором И. Если оба операнда не равны нулю, тогда условие становится истинным. (A && B) ложно.
|| Вызывается логическим оператором ИЛИ. Если какой-либо из двух операндов не равен нулю, условие становится истинным. (A || B) верно.
! Вызывается оператором логического НЕ. Используется для изменения логического состояния операнда на обратное. Если условие истинно, то оператор логического НЕ сделает ложным. ! (A && B) верно.

В следующей таблице показаны все логические операторы, поддерживаемые языком Go. Предположим переменнуюA верно и изменчиво B ложь, тогда -

Оператор Описание пример
&& Вызывается логическим оператором И. Если оба операнда ложны, то условие становится ложным. (A && B) ложно.
|| Вызывается логическим оператором ИЛИ. Если любой из двух операндов истинен, то условие становится истинным. (A || B) верно.
! Вызывается оператором логического НЕ. Используется для изменения логического состояния операнда на обратное. Если условие истинно, то оператор логического НЕ сделает его ложным. ! (A && B) верно.

Побитовые операторы

Поразрядные операторы работают с битами и выполняют побитовые операции. Таблицы истинности для &, | и ^ следующие:

п q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Предположим, что A = 60; и B = 13. В двоичном формате они будут следующими:

А = 0011 1100

В = 0000 1101

-----------------

A&B = 0000 1100

А | В = 0011 1101

A ^ B = 0011 0001

~ А = 1100 0011

Побитовые операторы, поддерживаемые языком C, перечислены в следующей таблице. Предположим, что переменная A содержит 60, а переменная B содержит 13, тогда -

Показать примеры

Оператор Описание пример
& Двоичный оператор И копирует бит в результат, если он существует в обоих операндах. (A и B) даст 12, что составляет 0000 1100
| Оператор двоичного ИЛИ копирует бит, если он существует в любом из операндов. (A | B) даст 61, то есть 0011 1101
^ Двоичный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. (A ^ B) даст 49, что составляет 0011 0001
<< Оператор двоичного сдвига влево. Значение левого операнда сдвигается влево на количество битов, указанное правым операндом. << 2 даст 240, что составляет 1111 0000
>> Оператор двоичного сдвига вправо. Значение левого операнда перемещается вправо на количество битов, указанное правым операндом. A >> 2 даст 15, что равно 0000 1111

Операторы присваивания

В следующей таблице перечислены все операторы присваивания, поддерживаемые языком Go.

Показать примеры

Оператор Описание пример
знак равно Простой оператор присваивания, присваивает значения из правых операндов левому операнду C = A + B присвоит значение A + B в C
+ = Добавить оператор присваивания И, он добавляет правый операнд к левому операнду и присваивает результат левому операнду C + = A эквивалентно C = C + A
знак равно Оператор вычитания И присваивания, он вычитает правый операнд из левого операнда и присваивает результат левому операнду C - = A эквивалентно C = C - A
знак равно Оператор умножения И присваивания, он умножает правый операнд на левый операнд и присваивает результат левому операнду C * = A эквивалентно C = C * A
знак равно Оператор деления И присваивания, он делит левый операнд на правый операнд и присваивает результат левому операнду C / = A эквивалентно C = C / A
знак равно Оператор модуля И присваивания, принимает модуль с использованием двух операндов и присваивает результат левому операнду C% = A эквивалентно C = C% A
<< = Левый сдвиг И оператор присваивания C << = 2 совпадает с C = C << 2
>> = Оператор сдвига вправо И присваивания C >> = 2 совпадает с C = C >> 2
знак равно Побитовый оператор присваивания И C & = 2 совпадает с C = C & 2
^ = побитовое исключающее ИЛИ и оператор присваивания C ^ = 2 совпадает с C = C ^ 2
| = побитовое включающее ИЛИ и оператор присваивания C | = 2 совпадает с C = C | 2

Разные операторы

Go Language поддерживает еще несколько важных операторов, включая sizeof и ?:.

Показать примеры

Оператор Описание пример
& Возвращает адрес переменной. & a; предоставляет фактический адрес переменной.
* Указатель на переменную. * а; предоставляет указатель на переменную.

Приоритет операторов в Go

Приоритет оператора определяет группировку терминов в выражении. Это влияет на то, как оценивается выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например, оператор умножения имеет более высокий приоритет, чем оператор сложения.

Например, x = 7 + 3 * 2; здесь x присваивается 13, а не 20, потому что оператор * имеет более высокий приоритет, чем +, поэтому он сначала умножается на 3 * 2, а затем складывается в 7.

Здесь операторы с наивысшим приоритетом отображаются вверху таблицы, а операторы с самым низким - внизу. Внутри выражения в первую очередь будут оцениваться операторы с более высоким приоритетом.

Показать примеры

Категория Оператор Ассоциативность
Постфикс () [] ->. ++ - - Слева направо
Унарный + -! ~ ++ - - (тип) * и размер Справа налево
Мультипликативный * /% Слева направо
Добавка + - Слева направо
сдвиг << >> Слева направо
Реляционный <<=>> = Слева направо
Равенство ==! = Слева направо
Побитовое И & Слева направо
Побитовое исключающее ИЛИ ^ Слева направо
Побитовое ИЛИ | Слева направо
Логическое И && Слева направо
Логическое ИЛИ || Слева направо
Назначение = + = - = * = / =% = >> = << = & = ^ = | = Справа налево
Запятая , Слева направо

Структуры принятия решений требуют, чтобы программист указал одно или несколько условий, которые должны быть оценены или проверены программой, вместе с оператором или операторами, которые должны быть выполнены, если условие определено как истинное, и, необязательно, другие операторы, которые должны выполняться, если условие определяется как ложь.

Ниже приводится общая форма типичной структуры принятия решений, встречающейся в большинстве языков программирования.

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

Старший Нет Заявление и описание
1 если заявление

An if statement состоит из логического выражения, за которым следует одно или несколько операторов.

2 если ... еще заявление

An if statement может сопровождаться необязательным else statement, который выполняется, когда логическое выражение ложно.

3 вложенные операторы if

Вы можете использовать один if или же else if заявление внутри другого if или же else if заявления).

4 оператор переключения

А switch оператор позволяет проверить переменную на равенство со списком значений.

5 выберите заявление

А select заявление похоже на switch утверждение с той разницей, что операторы case относятся к каналам связи.

Возможна ситуация, когда вам нужно выполнить блок кода несколько раз. Как правило, операторы выполняются последовательно: сначала выполняется первый оператор функции, затем второй и т. Д.

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

Оператор цикла позволяет нам выполнять оператор или группу операторов несколько раз, и ниже приводится общая форма оператора цикла на большинстве языков программирования:

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

Старший Нет Тип и описание петли
1 для цикла

Он выполняет последовательность операторов несколько раз и сокращает код, управляющий переменной цикла.

2 вложенные циклы

Это один или несколько циклов внутри любого цикла for.

Заявления контроля цикла

Операторы управления циклом изменяют нормальную последовательность выполнения. Когда выполнение покидает свою область видимости, все автоматические объекты, созданные в этой области, уничтожаются.

Go поддерживает следующие управляющие операторы -

Старший Нет Положение и описание управления
1 заявление о прерывании

Это завершает for loop или же switch оператор и передает выполнение оператору, следующему за циклом for или переключателем.

2 продолжить заявление

Это заставляет цикл пропускать оставшуюся часть своего тела и немедленно повторно проверять свое состояние перед повторением.

3 инструкция goto

Он передает управление помеченному оператору.

Бесконечный цикл

Цикл становится бесконечным, если его условие никогда не становится ложным. Для этой цели традиционно используется цикл for. Поскольку ни одно из трех выражений, образующих цикл for, не требуется, вы можете создать бесконечный цикл, оставив условное выражение пустым или передав ему true.

package main

import "fmt"

func main() {
   for true  {
       fmt.Printf("This loop will run forever.\n");
   }
}

Когда условное выражение отсутствует, оно считается истинным. У вас может быть выражение инициализации и приращения, но программисты на C чаще используют конструкцию for (;;) для обозначения бесконечного цикла.

Note - Вы можете прервать бесконечный цикл, нажав клавиши Ctrl + C.

Функция - это группа операторов, которые вместе выполняют задачу. Каждая программа Go имеет как минимум одну функцию, а именно:main(). Вы можете разделить свой код на отдельные функции. Как разделить код между различными функциями - решать вам, но логически разделение должно быть таким, чтобы каждая функция выполняла определенную задачу.

Функция declarationсообщает компилятору имя функции, возвращаемый тип и параметры. Функцияdefinition предоставляет фактическое тело функции.

Стандартная библиотека Go предоставляет множество встроенных функций, которые может вызывать ваша программа. Например, функцияlen()принимает аргументы различных типов и возвращает длину типа. Если ему передана строка, функция возвращает длину строки в байтах. Если ей передается массив, функция возвращает длину массива.

Функции также известны как method, sub-routine, или же procedure.

Определение функции

Общая форма определения функции на языке программирования Go следующая:

func function_name( [parameter list] ) [return_types]
{
   body of the function
}

Определение функции в языке программирования Go состоит из заголовка функции и тела функции . Вот все части функции -

  • Func - Начинает объявление функции.

  • Function Name- Это настоящее имя функции. Имя функции и список параметров вместе составляют сигнатуру функции.

  • Parameters- Параметр похож на заполнитель. Когда функция вызывается, вы передаете значение параметру. Это значение называется фактическим параметром или аргументом. Список параметров относится к типу, порядку и количеству параметров функции. Параметры не обязательны; то есть функция может не содержать параметров.

  • Return Type- Функция может возвращать список значений. Return_types - это список типов данных значений, возвращаемых функцией. Некоторые функции выполняют желаемые операции без возврата значения. В этом случае return_type не требуется.

  • Function Body - Он содержит набор операторов, определяющих, что делает функция.

пример

В следующем исходном коде показана функция с именем max(). Эта функция принимает два параметра num1 и num2 и возвращает максимум между двумя -

/* function returning the max between two numbers */
func max(num1, num2 int) int {
   /* local variable declaration */
   result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

Вызов функции

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

Когда программа вызывает функцию, управление программой передается вызываемой функции. Вызываемая функция выполняет определенную задачу, и когда выполняется ее оператор return или когда достигается закрывающая скобка, завершающая функцию, она возвращает управление программой обратно в основную программу.

Чтобы вызвать функцию, вам просто нужно передать необходимые параметры вместе с ее именем. Если функция возвращает значение, вы можете сохранить возвращенное значение. Например -

package main

import "fmt"

func main() {
   /* local variable definition */
   var a int = 100
   var b int = 200
   var ret int

   /* calling a function to get max value */
   ret = max(a, b)

   fmt.Printf( "Max value is : %d\n", ret )
}

/* function returning the max between two numbers */
func max(num1, num2 int) int {
   /* local variable declaration */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

Мы сохранили функцию max () вместе с функцией main () и скомпилировали исходный код. При запуске последнего исполняемого файла он даст следующий результат:

Max value is : 200

Возврат нескольких значений из функции

Функция Go может возвращать несколько значений. Например -

package main

import "fmt"

func swap(x, y string) (string, string) {
   return y, x
}
func main() {
   a, b := swap("Mahesh", "Kumar")
   fmt.Println(a, b)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Kumar Mahesh

Аргументы функции

Если функция должна использовать аргументы, она должна объявить переменные, которые принимают значения аргументов. Эти переменные называютсяformal parameters функции.

Формальные параметры ведут себя как другие локальные переменные внутри функции и создаются при входе в функцию и уничтожаются при выходе.

При вызове функции аргументы могут быть переданы в функцию двумя способами:

Старший Нет Тип звонка и описание
1 Звоните по цене

Этот метод копирует фактическое значение аргумента в формальный параметр функции. В этом случае изменения, внесенные в параметр внутри функции, не влияют на аргумент.

2 Звоните по ссылке

Этот метод копирует адрес аргумента в формальный параметр. Внутри функции адрес используется для доступа к фактическому аргументу, используемому в вызове. Это означает, что изменения, внесенные в параметр, влияют на аргумент.

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

Использование функции

Функцию можно использовать следующим образом:

Старший Нет Использование и описание функции
1 Функция как значение

Функции можно создавать на лету и использовать в качестве значений.

2 Закрытие функций

Замыкания функций являются анонимными функциями и могут использоваться в динамическом программировании.

3 Метод

Методы - это специальные функции с приемником.

Область видимости в любом программировании - это область программы, в которой может существовать определенная переменная, и за ее пределами доступ к переменной невозможен. Есть три места, где переменные могут быть объявлены на языке программирования Go:

  • Внутри функции или блока (local переменные)

  • Вне всех функций (global переменные)

  • В определении параметров функции (formal параметры)

Давайте узнаем, что такое local и global переменные и что такое formal параметры.

Локальные переменные

Переменные, объявленные внутри функции или блока, называются локальными переменными. Они могут использоваться только операторами, которые находятся внутри этой функции или блока кода. Локальные переменные не известны функциям вне их собственных. В следующем примере используются локальные переменные. Здесь все переменные a, b и c являются локальными для функции main ().

package main

import "fmt"

func main() {
   /* local variable declaration */
   var a, b, c int 

   /* actual initialization */
   a = 10
   b = 20
   c = a + b

   fmt.Printf ("value of a = %d, b = %d and c = %d\n", a, b, c)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

value of a = 10, b = 20 and c = 30

Глобальные переменные

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

Доступ к глобальной переменной может получить любая функция. То есть глобальная переменная доступна для использования во всей программе после ее объявления. В следующем примере используются как глобальные, так и локальные переменные -

package main

import "fmt"
 
/* global variable declaration */
var g int
 
func main() {
   /* local variable declaration */
   var a, b int

   /* actual initialization */
   a = 10
   b = 20
   g = a + b

   fmt.Printf("value of a = %d, b = %d and g = %d\n", a, b, g)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

value of a = 10, b = 20 and g = 30

Программа может иметь одно и то же имя для локальных и глобальных переменных, но значение локальной переменной внутри функции имеет приоритет. Например -

package main

import "fmt"
 
/* global variable declaration */
var g int = 20
 
func main() {
   /* local variable declaration */
   var g int = 10
 
   fmt.Printf ("value of g = %d\n",  g)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

value of g = 10

Формальные параметры

Формальные параметры обрабатываются как локальные переменные внутри этой функции и имеют преимущество перед глобальными переменными. Например -

package main

import "fmt"
 
/* global variable declaration */
var a int = 20;
 
func main() {
   /* local variable declaration in main function */
   var a int = 10
   var b int = 20
   var c int = 0

   fmt.Printf("value of a in main() = %d\n",  a);
   c = sum( a, b);
   fmt.Printf("value of c in main() = %d\n",  c);
}
/* function to add two integers */
func sum(a, b int) int {
   fmt.Printf("value of a in sum() = %d\n",  a);
   fmt.Printf("value of b in sum() = %d\n",  b);

   return a + b;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

value of a in main() = 10
value of a in sum() = 10
value of b in sum() = 20
value of c in main() = 30

Инициализация локальных и глобальных переменных

Локальные и глобальные переменные инициализируются значением по умолчанию, равным 0; в то время как указатели инициализируются нулем.

Тип данных Начальное значение по умолчанию
int 0
float32 0
указатель ноль

Строки, которые широко используются в программировании на Go, представляют собой фрагменты байтов, доступные только для чтения. В языке программирования Go строкиslices. Платформа Go предоставляет различные библиотеки для управления строками.

  • unicode
  • regexp
  • strings

Создание строк

Самый прямой способ создать строку - написать -

var greeting = "Hello world!"

Каждый раз, когда он встречает строковый литерал в вашем коде, компилятор создает строковый объект со своим значением в данном случае «Hello world!».

Строковый литерал содержит допустимые последовательности UTF-8, называемые рунами. Строка содержит произвольные байты.

package main

import "fmt"

func main() {
   var greeting =  "Hello world!"
   
   fmt.Printf("normal string: ")
   fmt.Printf("%s", greeting)
   fmt.Printf("\n")
   fmt.Printf("hex bytes: ")
   
   for i := 0; i < len(greeting); i++ {
       fmt.Printf("%x ", greeting[i])
   }
   fmt.Printf("\n")
   
   const sampleText = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98" 
   /*q flag escapes unprintable characters, with + flag it escapses non-ascii 
   characters as well to make output unambigous  
   */
   fmt.Printf("quoted string: ")
   fmt.Printf("%+q", sampleText)
   fmt.Printf("\n")  
}

Это даст следующий результат -

normal string: Hello world!
hex bytes: 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 
quoted string: "\xbd\xb2=\xbc \u2318"

Note - Строковый литерал неизменяем, поэтому после его создания строковый литерал не может быть изменен.

Длина строки

Метод len (str) возвращает количество байтов, содержащихся в строковом литерале.

package main

import "fmt"

func main() {
   var greeting =  "Hello world!"
   
   fmt.Printf("String Length is: ")
   fmt.Println(len(greeting))  
}

Это даст следующий результат -

String Length is : 12

Объединение строк

Пакет strings включает метод join для объединения нескольких строк -

strings.Join(sample, " ")

Join объединяет элементы массива для создания единой строки. Второй параметр - разделитель, который ставится между элементами массива.

Давайте посмотрим на следующий пример -

package main

import ("fmt" "math" )"fmt" "strings")

func main() {
   greetings :=  []string{"Hello","world!"}   
   fmt.Println(strings.Join(greetings, " "))
}

Это даст следующий результат -

Hello world!

Язык программирования Go предоставляет структуру данных, называемую the array, который может хранить последовательную коллекцию фиксированного размера элементов одного типа. Массив используется для хранения набора данных, но часто бывает более полезно думать о массиве как о коллекции переменных одного типа.

Вместо объявления отдельных переменных, таких как число0, число1, ... и число99, вы объявляете одну переменную массива, например числа, и используете числа [0], числа [1] и ..., числа [99] для представления отдельные переменные. Доступ к определенному элементу в массиве осуществляется по индексу.

Все массивы состоят из непрерывных ячеек памяти. Самый низкий адрес соответствует первому элементу, а самый высокий адрес - последнему элементу.

Объявление массивов

Чтобы объявить массив в Go, программист указывает тип элементов и количество элементов, необходимых для массива, следующим образом:

var variable_name [SIZE] variable_type

Это называется одномерным массивом. ВarraySize должен быть целочисленной константой больше нуля и typeможет быть любым допустимым типом данных Go. Например, чтобы объявить массив из 10 элементов с именемbalance типа float32 используйте этот оператор -

var balance [10] float32

Вот, balance представляет собой массив переменных, который может содержать до 10 чисел с плавающей запятой.

Инициализация массивов

Вы можете инициализировать массив в Go либо один за другим, либо с помощью одного оператора следующим образом:

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

Количество значений в скобках {} не может быть больше количества элементов, объявленных нами для массива в квадратных скобках [].

Если вы не укажете размер массива, будет создан массив, достаточно большой, чтобы вместить инициализацию. Поэтому если написать -

var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}

Вы создадите точно такой же массив, как и в предыдущем примере. Ниже приведен пример назначения одного элемента массива:

balance[4] = 50.0

Выше оператор присваивает номер элемента 5 - й в массиве со значением 50,0. Все массивы имеют 0 в качестве индекса своего первого элемента, который также называется базовым индексом, а последний индекс массива будет иметь общий размер массива минус 1. Ниже приведено графическое представление того же массива, который мы обсуждали выше.

Доступ к элементам массива

Доступ к элементу осуществляется путем индексации имени массива. Это делается путем помещения индекса элемента в квадратные скобки после имени массива. Например -

float32 salary = balance[9]

Приведенный выше оператор возьмет 10- й элемент из массива и присвоит значение переменной зарплаты. Ниже приведен пример, в котором будут использоваться все три вышеупомянутых концепции, а именно. объявление, присвоение и доступ к массивам -

package main

import "fmt"

func main() {
   var n [10]int /* n is an array of 10 integers */
   var i,j int

   /* initialize elements of array n to 0 */         
   for i = 0; i < 10; i++ {
      n[i] = i + 100 /* set element at location i to i + 100 */
   }
   /* output each array element's value */
   for j = 0; j < 10; j++ {
      fmt.Printf("Element[%d] = %d\n", j, n[j] )
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

Подробнее о массивах

Есть важные концепции, связанные с массивом, которые должны быть понятны программисту на Go:

Старший Нет Концепция и описание
1 Многомерные массивы

Go поддерживает многомерные массивы. Простейшей формой многомерного массива является двумерный массив.

2 Передача массивов в функции

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

Указатели в Go учить легко и весело. Некоторые задачи программирования на Go легче выполнять с помощью указателей, а другие задачи, такие как вызов по ссылке, невозможно выполнить без использования указателей. Поэтому становится необходимым выучить указатели, чтобы стать идеальным программистом на Go.

Как вы знаете, каждая переменная является ячейкой памяти, и каждая ячейка памяти имеет свой адрес, доступ к которому можно получить с помощью оператора амперсанда (&), который обозначает адрес в памяти. Рассмотрим следующий пример, который напечатает адрес определенных переменных -

package main

import "fmt"

func main() {
   var a int = 10   
   fmt.Printf("Address of a variable: %x\n", &a  )
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Address of a variable: 10328000

Итак, вы поняли, что такое адрес памяти и как к нему получить доступ. Теперь давайте посмотрим, что такое указатели.

Что такое указатели?

А pointer- это переменная, значение которой является адресом другой переменной, т. е. прямым адресом ячейки памяти. Как и любую переменную или константу, вы должны объявить указатель, прежде чем вы сможете использовать его для хранения любого адреса переменной. Общая форма объявления переменной-указателя -

var var_name *var-type

Вот, type- базовый тип указателя; это должен быть допустимый тип данных C иvar-nameэто имя переменной-указателя. Звездочка *, которую вы использовали для объявления указателя, - это та же звездочка, которую вы используете для умножения. Однако в этом заявлении звездочка используется для обозначения переменной как указателя. Ниже приведено действительное объявление указателя -

var ip *int        /* pointer to an integer */
var fp *float32    /* pointer to a float */

Фактический тип данных значения всех указателей, будь то целое число, число с плавающей запятой или иное, один и тот же, длинное шестнадцатеричное число, представляющее адрес памяти. Единственное различие между указателями разных типов данных - это тип данных переменной или константы, на которые указывает указатель.

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

Есть несколько важных операций, которые мы часто выполняем с указателями: (а) мы определяем переменные-указатели, (б) присваиваем адрес переменной указателю и (в) получаем доступ к значению по адресу, хранящемуся в переменной-указателе. .

Все эти операции выполняются с помощью унарного оператора *, который возвращает значение переменной, расположенной по адресу, указанному ее операндом. В следующем примере показано, как выполнять эти операции -

package main

import "fmt"

func main() {
   var a int = 20   /* actual variable declaration */
   var ip *int      /* pointer variable declaration */

   ip = &a  /* store address of a in pointer variable*/

   fmt.Printf("Address of a variable: %x\n", &a  )

   /* address stored in pointer variable */
   fmt.Printf("Address stored in ip variable: %x\n", ip )

   /* access the value using the pointer */
   fmt.Printf("Value of *ip variable: %d\n", *ip )
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Address of var variable: 10328000
Address stored in ip variable: 10328000
Value of *ip variable: 20

Нет указателей в Go

Компилятор Go присваивает переменной-указателю значение Nil в случае, если у вас нет точного адреса для назначения. Это делается во время объявления переменной. Указатель, которому присвоено значение nil, называетсяnil указатель.

Указатель nil - это константа со значением нуля, определенная в нескольких стандартных библиотеках. Рассмотрим следующую программу -

package main

import "fmt"

func main() {
   var  ptr *int

   fmt.Printf("The value of ptr is : %x\n", ptr  )
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

The value of ptr is 0

В большинстве операционных систем программам не разрешен доступ к памяти по адресу 0, поскольку эта память зарезервирована операционной системой. Однако адрес памяти 0 имеет особое значение; он сигнализирует, что указатель не предназначен для указания на доступную ячейку памяти. Но по соглашению, если указатель содержит значение nil (ноль), предполагается, что он ни на что не указывает.

Чтобы проверить указатель nil, вы можете использовать оператор if следующим образом:

if(ptr != nil)     /* succeeds if p is not nil */
if(ptr == nil)    /* succeeds if p is null */

Подробнее о указателях Go

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

Старший Нет Концепция и описание
1 Go - массив указателей

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

2 Перейти - указатель на указатель

Go позволяет вам иметь указатель на указатель и так далее.

3 Передача указателей на функции в Go

Передача аргумента по ссылке или по адресу позволяет изменять переданный аргумент в вызывающей функции вызываемой функцией.

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

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

  • Title
  • Author
  • Subject
  • Идентификатор книги

В таком сценарии очень полезны конструкции.

Определение структуры

Чтобы определить структуру, вы должны использовать type и structзаявления. Оператор struct определяет новый тип данных с несколькими членами для вашей программы. Оператор типа связывает имя с типом, который в нашем случае является структурой. Формат оператора структуры следующий:

type struct_variable_type struct {
   member definition;
   member definition;
   ...
   member definition;
}

После определения типа структуры его можно использовать для объявления переменных этого типа, используя следующий синтаксис.

variable_name := structure_variable_type {value1, value2...valuen}

Доступ к членам структуры

Для доступа к любому члену структуры мы используем member access operator (.).Оператор доступа к члену кодируется как точка между именем переменной структуры и элементом структуры, к которому мы хотим получить доступ. Вы бы использовалиstructключевое слово для определения переменных структурного типа. В следующем примере объясняется, как использовать структуру -

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books    /* Declare Book1 of type Book */
   var Book2 Books    /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700
 
   /* print Book1 info */
   fmt.Printf( "Book 1 title : %s\n", Book1.title)
   fmt.Printf( "Book 1 author : %s\n", Book1.author)
   fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
   fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

   /* print Book2 info */
   fmt.Printf( "Book 2 title : %s\n", Book2.title)
   fmt.Printf( "Book 2 author : %s\n", Book2.author)
   fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
   fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Book 1 title      : Go Programming
Book 1 author     : Mahesh Kumar
Book 1 subject    : Go Programming Tutorial
Book 1 book_id    : 6495407
Book 2 title      : Telecom Billing
Book 2 author     : Zara Ali
Book 2 subject    : Telecom Billing Tutorial
Book 2 book_id    : 6495700

Структуры как аргументы функций

Вы можете передать структуру в качестве аргумента функции так же, как и любую другую переменную или указатель. Вы должны получить доступ к структурным переменным так же, как в приведенном выше примере -

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books    /* Declare Book1 of type Book */
   var Book2 Books    /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700
 
   /* print Book1 info */
   printBook(Book1)

   /* print Book2 info */
   printBook(Book2)
}
func printBook( book Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Book title     : Go Programming
Book author    : Mahesh Kumar
Book subject   : Go Programming Tutorial
Book book_id   : 6495407
Book title     : Telecom Billing
Book author    : Zara Ali
Book subject   : Telecom Billing Tutorial
Book book_id   : 6495700

Указатели на структуры

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

var struct_pointer *Books

Теперь вы можете сохранить адрес структурной переменной в указанной выше переменной-указателе. Чтобы найти адрес структурной переменной, поместите оператор & перед именем структуры следующим образом:

struct_pointer = &Book1;

Чтобы получить доступ к членам структуры с помощью указателя на эту структуру, вы должны использовать символ "." оператор следующим образом -

struct_pointer.title;

Давайте перепишем приведенный выше пример, используя указатель на структуру -

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books   /* Declare Book1 of type Book */
   var Book2 Books   /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700
 
   /* print Book1 info */
   printBook(&Book1)

   /* print Book2 info */
   printBook(&Book2)
}
func printBook( book *Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Book title     : Go Programming
Book author    : Mahesh Kumar
Book subject   : Go Programming Tutorial
Book book_id   : 6495407
Book title     : Telecom Billing
Book author    : Zara Ali
Book subject   : Telecom Billing Tutorial
Book book_id   : 6495700

Go Slice - это абстракция над Go Array. Go Array позволяет вам определять переменные, которые могут содержать несколько элементов данных одного и того же типа, но не предоставляет никаких встроенных методов для динамического увеличения его размера или получения собственного подмассива. Ломтики преодолевают это ограничение. Он предоставляет множество служебных функций, необходимых для Array, и широко используется в программировании на Go.

Определение среза

Чтобы определить срез, вы можете объявить его как массив без указания его размера. В качестве альтернативы вы можете использоватьmake функция для создания среза.

var numbers []int /* a slice of unspecified size */
/* numbers == []int{0,0,0,0,0}*/
numbers = make([]int,5,5) /* a slice of length 5 and capacity 5*/

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

Срез - это абстракция над массивом. Фактически в качестве базовой структуры используются массивы. Вlen() функция возвращает элементы, представленные в срезе, где cap()функция возвращает емкость среза (то есть, сколько элементов в нем можно разместить). В следующем примере объясняется использование среза -

package main

import "fmt"

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

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

len = 3 cap = 5 slice = [0 0 0]

Нулевой ломтик

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

package main

import "fmt"

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

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

len = 0 cap = 0 slice = []
slice is nil

Нарезка

Slice позволяет указывать нижнюю и верхнюю границы, чтобы получить его часть, используя[lower-bound:upper-bound]. Например -

package main

import "fmt"

func main() {
   /* create a slice */
   numbers := []int{0,1,2,3,4,5,6,7,8}   
   printSlice(numbers)
   
   /* print the original slice */
   fmt.Println("numbers ==", numbers)
   
   /* print the sub slice starting from index 1(included) to index 4(excluded)*/
   fmt.Println("numbers[1:4] ==", numbers[1:4])
   
   /* missing lower bound implies 0*/
   fmt.Println("numbers[:3] ==", numbers[:3])
   
   /* missing upper bound implies len(s)*/
   fmt.Println("numbers[4:] ==", numbers[4:])
   
   numbers1 := make([]int,0,5)
   printSlice(numbers1)
   
   /* print the sub slice starting from index 0(included) to index 2(excluded) */
   number2 := numbers[:2]
   printSlice(number2)
   
   /* print the sub slice starting from index 2(included) to index 5(excluded) */
   number3 := numbers[2:5]
   printSlice(number3)
   
}
func printSlice(x []int){
   fmt.Printf("len = %d cap = %d slice = %v\n", len(x), cap(x),x)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

len = 9 cap = 9 slice = [0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
len = 0 cap = 5 slice = []
len = 2 cap = 9  slice = [0 1]
len = 3 cap = 7 slice = [2 3 4]

Функции append () и copy ()

Увеличить емкость среза можно с помощью append()функция. С помощьюcopy()функция, содержимое исходного слайса копируется в целевой слайс. Например -

package main

import "fmt"

func main() {
   var numbers []int
   printSlice(numbers)
   
   /* append allows nil slice */
   numbers = append(numbers, 0)
   printSlice(numbers)
   
   /* add one element to slice*/
   numbers = append(numbers, 1)
   printSlice(numbers)
   
   /* add more than one element at a time*/
   numbers = append(numbers, 2,3,4)
   printSlice(numbers)
   
   /* create a slice numbers1 with double the capacity of earlier slice*/
   numbers1 := make([]int, len(numbers), (cap(numbers))*2)
   
   /* copy content of numbers to numbers1 */
   copy(numbers1,numbers)
   printSlice(numbers1)   
}
func printSlice(x []int){
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

len = 0 cap = 0 slice = []
len = 1 cap = 2 slice = [0]
len = 2 cap = 2 slice = [0 1]
len = 5 cap = 8 slice = [0 1 2 3 4]
len = 5 cap = 16 slice = [0 1 2 3 4]

В range ключевое слово используется в forцикл для перебора элементов массива, фрагмента, канала или карты. С массивом и срезами он возвращает индекс элемента как целое число. С картами он возвращает ключ следующей пары ключ-значение. Диапазон возвращает одно или два значения. Если слева от выражения диапазона используется только одно значение, это первое значение в следующей таблице.

Выражение диапазона 1-е значение 2-е значение (необязательно)
Массив или фрагмент [n] E индекс я int a [i] E
String s тип строки индекс я int руна int
map m map [K] V ключ k K значение m [k] V
канал c chan E элемент e E никто

пример

В следующем абзаце показано, как использовать диапазон -

package main

import "fmt"

func main() {
   /* create a slice */
   numbers := []int{0,1,2,3,4,5,6,7,8} 
   
   /* print the numbers */
   for i:= range numbers {
      fmt.Println("Slice item",i,"is",numbers[i])
   }
   
   /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo"}
   
   /* print map using keys*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* print map using key-value*/
   for country,capital := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",capital)
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Slice item 0 is 0
Slice item 1 is 1
Slice item 2 is 2
Slice item 3 is 3
Slice item 4 is 4
Slice item 5 is 5
Slice item 6 is 6
Slice item 7 is 7
Slice item 8 is 8
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo

Go предоставляет еще один важный тип данных - map, который сопоставляет уникальные ключи со значениями. Ключ - это объект, который вы используете для получения значения позже. Имея ключ и значение, вы можете сохранить значение в объекте Map. После того, как значение сохранено, вы можете получить его, используя его ключ.

Определение карты

Вы должны использовать make функция для создания карты.

/* declare a variable, by default map will be nil*/
var map_variable map[key_data_type]value_data_type

/* define the map as nil map can not be assigned any value*/
map_variable = make(map[key_data_type]value_data_type)

пример

В следующем примере показано, как создать и использовать карту.

package main

import "fmt"

func main() {
   var countryCapitalMap map[string]string
   /* create a map*/
   countryCapitalMap = make(map[string]string)
   
   /* insert key-value pairs in the map*/
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
   
   /* print map using keys*/
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* test if entry is present in the map or not*/
   capital, ok := countryCapitalMap["United States"]
   
   /* if ok is true, entry is present otherwise entry is absent*/
   if(ok){
      fmt.Println("Capital of United States is", capital)  
   } else {
      fmt.Println("Capital of United States is not present") 
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Capital of India is New Delhi
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of United States is not present

Функция delete ()

Функция delete () используется для удаления записи с карты. Требуется карта и соответствующий ключ, который нужно удалить. Например -

package main

import "fmt"

func main() {   
   /* create a map*/
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}
   
   fmt.Println("Original map")   
   
   /* print map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   
   /* delete an entry */
   delete(countryCapitalMap,"France");
   fmt.Println("Entry for France is deleted")  
   
   fmt.Println("Updated map")   
   
   /* print map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Original Map
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted
Updated Map
Capital of India is New Delhi
Capital of Italy is Rome
Capital of Japan is Tokyo

Рекурсия - это процесс самоподобного повторения элементов. Та же концепция применима и к языкам программирования. Если программа позволяет вызвать функцию внутри той же функции, то это называется рекурсивным вызовом функции. Взгляните на следующий пример -

func recursion() {
   recursion() /* function calls itself */
}
func main() {
   recursion()
}

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

Примеры рекурсии в Go

Рекурсивные функции очень полезны для решения многих математических задач, таких как вычисление факториала числа, создание ряда Фибоначчи и т. Д.

Пример 1: Расчет факториала с использованием рекурсии в Go

В следующем примере вычисляется факториал заданного числа с использованием рекурсивной функции -

package main

import "fmt"

func factorial(i int)int {
   if(i <= 1) {
      return 1
   }
   return i * factorial(i - 1)
}
func main() { 
   var i int = 15
   fmt.Printf("Factorial of %d is %d", i, factorial(i))
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Factorial of 15 is 1307674368000

Пример 2: ряды Фибоначчи с использованием рекурсии в Go

В следующем примере показано, как сгенерировать ряд Фибоначчи данного числа с помощью рекурсивной функции -

package main

import "fmt"

func fibonaci(i int) (ret int) {
   if i == 0 {
      return 0
   }
   if i == 1 {
      return 1
   }
   return fibonaci(i-1) + fibonaci(i-2)
}
func main() {
   var i int
   for i = 0; i < 10; i++ {
      fmt.Printf("%d ", fibonaci(i))
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

0 1 1 2 3 5 8 13 21 34

Приведение типов - это способ преобразования переменной из одного типа данных в другой тип данных. Например, если вы хотите сохранить длинное значение в простом целочисленном, вы можете ввести cast long в int. Вы можете преобразовывать значения из одного типа в другой, используяcast operator. Его синтаксис следующий -

type_name(expression)

пример

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

package main

import "fmt"

func main() {
   var sum int = 17
   var count int = 5
   var mean float32
   
   mean = float32(sum)/float32(count)
   fmt.Printf("Value of mean : %f\n",mean)
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Value of mean : 3.400000

Программирование на Go предоставляет другой тип данных, называемый interfacesкоторый представляет собой набор сигнатур методов. Тип данных struct реализует эти интерфейсы, чтобы иметь определения методов для сигнатуры методов интерфейсов.

Синтаксис

/* define an interface */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* define a struct */
type struct_name struct {
   /* variables */
}

/* implement interface methods*/
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* method implementation */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* method implementation */
}

пример

package main

import (
   "fmt" 
   "math" 
)

/* define an interface */
type Shape interface {
   area() float64
}

/* define a circle */
type Circle struct {
   x,y,radius float64
}

/* define a rectangle */
type Rectangle struct {
   width, height float64
}

/* define a method for circle (implementation of Shape.area())*/
func(circle Circle) area() float64 {
   return math.Pi * circle.radius * circle.radius
}

/* define a method for rectangle (implementation of Shape.area())*/
func(rect Rectangle) area() float64 {
   return rect.width * rect.height
}

/* define a method for shape */
func getArea(shape Shape) float64 {
   return shape.area()
}

func main() {
   circle := Circle{x:0,y:0,radius:5}
   rectangle := Rectangle {width:10, height:5}
   
   fmt.Printf("Circle area: %f\n",getArea(circle))
   fmt.Printf("Rectangle area: %f\n",getArea(rectangle))
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Circle area: 78.539816
Rectangle area: 50.000000

Программирование на Go обеспечивает довольно простую структуру обработки ошибок со встроенным типом интерфейса ошибок следующего объявления:

type error interface {
   Error() string
}

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

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}

Используйте возвращаемое значение и сообщение об ошибке.

result, err:= Sqrt(-1)

if err != nil {
   fmt.Println(err)
}

пример

package main

import "errors"
import "fmt"
import "math"

func Sqrt(value float64)(float64, error) {
   if(value < 0){
      return 0, errors.New("Math: negative number passed to Sqrt")
   }
   return math.Sqrt(value), nil
}
func main() {
   result, err:= Sqrt(-1)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
   
   result, err = Sqrt(9)

   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(result)
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Math: negative number passed to Sqrt
3