Go in a nutshell
  • Go in a nutshell
  • Введение
  • Родословная или Should I Go?
  • Hello, world!
  • Базовые типы данных
  • Go - установка, сборка
  • Алфавит и пакеты
  • Синтаксис
  • Приведение типов
  • Операторы
  • Константы
  • Управление потоком
  • Массивы, срезы, отображения
  • Именованные типы и структуры
  • Указатели и оператор new
  • Функции
  • Работа с параметрами командной строки
  • Завершение работы программы
  • Методы
Powered by GitBook
On this page
  • Указатели
  • Оператор new

Was this helpful?

Указатели и оператор new

Указатели

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

Синтаксис аналогичен таковому в С/С++. Точно как и в С, присутствует 2 оператора: астериск * - так называемое разыменование указателя, и амперсанд & - взятие адреса. Проиллюстрируем это.

package main

import (
	"fmt"
)

func main() {

	var i int = 0 // переменная типа int
	var p *int // объявление указателя на int
	p = &i // p присваивается адрес i
	fmt.Println("Адрес:", p) //выведем адрес
	fmt.Println("Значение:", *p) //выведем значение (разыменование указателя)
	*p = 5 // присвоение нового значения по данному адресу
	fmt.Println("i =", i) // исходная переменная i изменилась

}
//Результат:
//Адрес: 0x40e020
//Значение: 0
//i = 5

Приведём более полезный пример - чтение пользовательского ввода:

package main

import (
	"fmt"
)

func main() {
	input := ""
	for {
		fmt.Println("Введите текст (q для выхода) :")
		fmt.Scan(&input) //используем взятие адреса!		
		if input == "q" {
			fmt.Println("Пока!..")
			break
		}
		fmt.Println("Вы ввели: ", input)
	}

}
//Результат:
//Введите текст (q для выхода) :
//Привет!
//Вы ввели:  Привет!
//Введите текст (q для выхода) :
//q
//Пока!..

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

Оператор new

Что в языке Go делает оператор new? Ответ лаконичен - он создаёт указатели. Опробуем его в деле.

package main

import (
	"fmt"
)

type T struct {
	a, b int
}

func main() {

	i := new(int) // указатель на int
	fmt.Println(i) // в нём адрес
	fmt.Printf("Type of i is %T\n", i) // прочитаем тип
	fmt.Println(*i) // разыменование указателя, то есть взятие значения
	
	t := new(T) // указатель на структуру T
	fmt.Println(t)
	fmt.Printf("Type of t is %T\n", t)
	fmt.Println(*t)

}
//Результат:
//0xc00000a0e0
//Type of i is *int
//0
//&{0 0}
//Type of t is *main.T
//{0 0}

Как видите, всё достаточно прозрачно. Но на самом деле, оператор new применяется нечасто. В практике языка Go, обычно прибегают к явному объявлению указателей. Отчего чаще поступают так или иначе - на этот вопрос у автора нет точного ответа. Так или иначе - оператор new - это полноправный инструмент, которым можно и нужно пользоваться.

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

package main

import (
	"github.com/gorilla/websocket"
	"net/http"	
)

/* глобальный дескриптор WebSocket соединения - указатель на указатель
так как сама импортируемая переменная типа websocket.Conn
является указателем! */
var wSconn **websocket.Conn // указатель на указатель!

// Создаётся WebSocket upgrader
var upgrader = websocket.Upgrader{
	ReadBufferSize:  4096,
	WriteBufferSize: 4096,
	CheckOrigin:     func(r *http.Request) bool { return true },
}

func MainHandler(w http.ResponseWriter, r *http.Request) {

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer conn.Close()	

//После установки соединения устанавливаем глобальный дескриптор
	wSconn = &conn

// далее продолжение работы функции ===================
}

/*Теперь глобальный дескриптор может быть использован в любом месте кода
для отправки сообщений в вебсокет*/

	buf := []byte("Hello, world!")
	conn := *wSconn
	err := conn.WriteMessage(websocket.TextMessage, buf)
	if err != nil {
			log.Println("Error : ", err)
		}


На этом рассмотрение предмета указателей можно считать достаточно полным. Позже мы ещё встретимся с ними, изучая функции и методы, работу с SQL, сетевое программирование. Дальше - больше.

Раунд!

PreviousИменованные типы и структурыNextФункции

Last updated 5 years ago

Was this helpful?