Грандиозный FAQ по Go Lang

Какие максимальные значения int и uint в Go?

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

const MaxUint = ^uint(0)
const MinUint = 0
const MaxInt = int(MaxUint >> 1)
const MinInt = -MaxInt - 1

А вот полный перечень целочисленных типов и их диапазонов:

  • uint8 : 0 to 255
  • uint16 : 0 to 65 535
  • uint32 : 0 to 4 294 967 295
  • uint64 : 0 to 18 446 744 073 709 551 615
  • int8 : -128 to 127
  • int16 : -32 768 to 3 2767
  • int32 : -2 147 483 648 to  2147 483 647
  • int64 : -9 223 372 036 854 775 808 to 9 223 372 036 854 775 807

Ещё один способ сделать это:

func printMinMaxValue() {
    // integer max
    fmt.Printf("max int64 = %+v\n", math.MaxInt64)
    fmt.Printf("max int32 = %+v\n", math.MaxInt32)
    fmt.Printf("max int16 = %+v\n", math.MaxInt16)
    // integer min
    fmt.Printf("min int64 = %+v\n", math.MinInt64)
    fmt.Printf("min int32 = %+v\n", math.MinInt32)
    fmt.Printf("max flloat64= %+v\n", math.MaxFloat64)
    fmt.Printf("max float32= %+v\n", math.MaxFloat32)
    // etc you can see more int the `math`package
}
max int64 = 9223372036854775807
max int32 = 2147483647
max int16 = 32767
min int64 = -9223372036854775808
min int32 = -2147483648
max flloat64= 1.7976931348623157e+308
max float32= 3.4028234663852886e+38

fatal error: concurrent map read and map write

Это очень неприятная ошибка, так как отловить её на этапе разработки или тестирования достаточно сложно, а вот в продакшене при высокой нагрузке она моментально зафаталит приложение. Суть такова: несколько потоков исполнения (горутин) одновременно хотят прочитать и записать данные в переменную с типом map.

Go отлавливает подобную ситуацию в runtime и выбрасывает фатальную ошибку. Иначе конкурентный доступ к одной переменной может привести к несогласованности этих данных. Решается достаточно просто: нужно установить блокировку перед тем как работать с данной переменной. По сути нужно сделать работу с этим значением однопоточным с помощью реализации mutex из пакета sync:

var mutex sync.Mutex
func request() {
	mutex.Lock()
	cntRequests["something"]++
	mutex.Unlock()
}

К сожалению, подобные ситуации невозможно отловить с помощью режима обнаружения race conditions.

Как в Go превратить массив байтов в строку

Самый простой способ:

string(data[:])

Можно также указать необходимый диапазон байт для конвертации:

string(data[:150])

Однако, при использовании данного способа в отладчике через evaluate будет конвертирована не вся строка, а только её часть.

Как в Go Lang вывести строку по указателю?

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

0xc00021e160

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

fmt.Fprint(httpResponse, *responseData)

Runtime error: assignment to entry in nil map

Такая ошибка происходит во время попытки сохранения значения в не проинициализированный map. При этом объявление переменной инициализацией не считается:

var myMap map[string] uint64

Нужно дополнительно вызывать:

myMap = make(map[string] uint64)

Как в Go обрабатывать ошибки в стиле try-catch?

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

data, e := exec()
if nil != e {
	switch e.(type) {
	case NotFoundError:
		return nil, e
	case FatalError:
		return nil, e
	default:
		log.Println("Error: " + e.Error())
	}
}

Как в Go создавать свои типы ошибок?

Ошибкой в Go считается любая структура соответствующая интерфейсу:

type error interface {
	Error() string
}

Например:

type FatalError struct {
	error error
}
func (err FatalError) Error() string {
	return err.error.Error()
}

Использовать можно так:

if err := json.Unmarshal(body, &data); err != nil {
	return nil, FatalError{error: err}
}

Как в Go создавать типы для функций?

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

type execFunc = func(client Client) (*string, error)

Использовать можно так:

var exec execFunc
exec = func(client Client) (*string, error) {
	return webMediaInfo(media, *client.Client)
}