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

## Указатели

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

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

```go
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
```

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

```go
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**? Ответ лаконичен - он создаёт указатели. Опробуем его в деле.

```go
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** применяется нечаст&#x43E;**.** В практике языка Go, обычно прибегают к явному объявлению указателе&#x439;**.** Отчего чаще поступают так или иначе - на этот вопрос у автора нет точного ответа. Так или иначе - оператор **new** - это полноправный инструмент, которым можно и нужно пользоваться.

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

```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, сетевое программирование. Дальше - больше.

#### Раунд!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.golang.org.ua/ukazateli.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
