Странная точка Голанга

задняя часть Go PHP

Эта статьяЭти ямы в языке Goдва.

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

Можно ли скомпилировать следующий код?

import (
	"fmt"
)

func main(){
	array := make(map[int]func ()int)

	array[func()int{ return 10}()] = func()int{
		return 12
	}

	fmt.Println(array)
}```

**答案:**

Его можно нормально скомпилировать.



稍作改动,改为如下的情况,还能编译通过吗?

​```Go
import (
	"fmt"
)

func main(){
	array := make(map[func ()int]int)

	array[func()int{return 12}] = 10

	fmt.Println(array)
}```
**答案:**

Не могу скомпилировать.


在Go语言中,函数被看做是第一类值:(first-class values):函数和其他值一样,可以被赋值,可以传递给函数,可以从函数返回。也可以被当做是一种“函数类型”。例如:有函数``func square(n int) int { return n * n }``,那么就可以赋值``f := square``,而且还可以``fmt.Println(f(3))``(将打印出“9”)。
Go语言函数有两点很特别:
+ 函数值类型不能作为map的key
+ 函数值之间不可以比较,函数值只可以和nil作比较,函数类型的零值是``nil``

# 匿名函数作用域陷阱

请看下列代码输出什么?

​```Go
import (
	"fmt"
)

func main(){
	var msgs []func()
	array := []string{
		"1", "2", "3", "4",
	}

	for _, e := range array{

			msgs = append(msgs, func(){
			fmt.Println(e)
		})
	}

	for _, v := range msgs{
		v()
	}
}

Отвечать:

4
4
4
4

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

Если вы хотите вывести 1, 2, 3 и 4, вам нужно изменить на:

import (
	"fmt"
)

func main(){
	var msgs []func()
	array := []string{
		"1", "2", "3", "4",
	}

	for _, e := range array{
		elem := e
		msgs = append(msgs, func(){
			fmt.Println(elem)
		})
	}

	for _, v := range msgs{
		v()
	}
}

Фактически добавленоelem := eЭто кажется избыточным, но это не так.Таким образом, после каждого цикла локальные переменные, сохраненные в каждой анонимной функции, все в это время.elemЗначение , такие локальные переменные определены 4, каждый раз, когда цикл генерирует один.

[3]intа также[4]intне тот тип

Пожалуйста, взгляните на код и спросите выводtrueвсе ещеfalse

import (
    "fmt"
    "reflect"
)

func main(){
    arrayA := [...]int{1, 2, 3}
    arrayB := [...]int{1, 2, 3, 4}
    fmt.Println(reflect.TypeOf(arrayA) == reflect.TypeOf(arrayB))
}

ответ:

false

Длина массива является компонентом типа массива, поэтому [3]int и [4]int — это два разных типа массивов.

Массивы также можно инициализировать, указав индекс и соответствующее значение.

Например:

import (
    "fmt"
)

func main(){
    arrayA := [...]int{0:1, 2:1, 3:4}
    fmt.Println(arrayA)
}

выведет:

[1 0 1 4]

Немного какPHPОщущение массива, но не то:arrayAКакова его длина?

import (
    "fmt"
)

func main(){
    arrayA := [...]int{0:1, 2:1, 3:4}
    fmt.Println(len(arrayA))
}

ответ:

4

Правильно, определен массив с длиной массива 4, и длина массива указанного индекса связана со значением последнего индекса, например:r := [...]int{99:-1}определяет массив из 100 элементовr, выход последнего элемента равен -1, а остальные элементы инициализируются 0.

Не удается обратиться к элементу на карте&действовать

a := &ages["bob"] // compile error: cannot take address of map element

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

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

func main() {
    var sampleMap map[string]int
    sampleMap["test"] = 1
    fmt.Println(sampleMap)
}

Ошибка вывода:

panic: assignment to entry in nil map

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

Приведенный выше код можно изменить на:

func main() {
    var sampleMap map[string]int
    sampleMap = map[string]int {
        "test1":1,
    }
    sampleMap["test"] = 1
    fmt.Println(sampleMap)
}

может правильно вывести:

map[test1:1 test:1]

&dilbert.Positionа также(&dilbert).Positionэто отличается

&dilbert.Positionэквивалентно&(dilbert.Position)вместо(&dilbert).Position

См. пример:

Подскажите, пожалуйста, что на выходе?

func main(){
    type Employee struct {
        ID int
        Name string
        Address string
        DoB time.Time
        Position string
        Salary int
        ManagerID int
    }
    var dilbert Employee

    dilbert.Position = "123"

    position := &dilbert.Position
    fmt.Println(position)

}

вывод:

0xc42006c220

Выход - адрес памяти

изменить его, поставить&dilbert.Positionизменить на(&dilbert).Position

func main(){
    type Employee struct {
        ID int
        Name string
        Address string
        DoB time.Time
        Position string
        Salary int
        ManagerID int
    }
    var dilbert Employee

    dilbert.Position = "123"

    position := &dilbert.Position
    fmt.Println(position)

}

вывод:

123

Когда функция возвращает значение на языке Go, ей нельзя присвоить значение

См. пример ниже:

type Employee struct {
    ID int
    Name string
    Address string
    DoB time.Time
    Position string
    Salary int
    ManagerID int
}

func EmployeeByID(id int) Employee {
    return Employee{ID:id}
}

func main(){
    EmployeeByID(1).Salary = 0
}

Может ли он быть скомпилирован?

запустить, ошибка вывода:cannot assign to EmployeeByID(1).Salary

В этом примере функцияEmployeeById(id int)Возвращаемое значение имеет тип, его значениеEmployeeByID(1).SalaryЭто также тип значения; какова концепция типа значения? Типы значений и операторы присваиванияvar a = 1илиvar a = hello worldзнак равенства=правая сторона1,Hello worldЯвляется концептом, его нельзя назначать, можно назначать только переменные.

Процедура модификации следующая:

type Employee struct {
    ID int
    Name string
    Address string
    DoB time.Time
    Position string
    Salary int
    ManagerID int
}

func EmployeeByID(id int) Employee {
    return Employee{ID:id}
}

func main(){
    var a = EmployeeByID(1)
    a.Salary = 0
}

Это компилирует

При объявлении метода, если имя типа само по себе является указателем, оно не может появляться в получателе метода.

Пожалуйста, посмотрите следующий пример, будет ли он скомпилирован и пройден?

import (
	"fmt"
)

type littleGirl struct{
	Name string
	Age int
}

type girl *littleGirl

func(this girl) changeName(name string){
	this.Name = name
}

func main(){
	littleGirl := girl{Name:"Rose", Age:1}
	
	girl.changeName("yoyo")
	fmt.Println(littleGirl)
}

Отвечать:

不能编译通过,会提示“invalid receiver type girl(girl is a pointer type)”

Язык Go предусматривает, что только тип (Type) и указатель на них (*Type) являются двумя получателями, которые могут фигурировать в объявлении получателя Во избежание двусмысленности четко оговорено, что если само имя типа является указатель не допускается в приемнике.

Функции допускают nil указатели в качестве аргументов и nil в качестве приемников методов.

Пожалуйста, посмотрите следующий пример, можете ли вы его скомпилировать?

import (
	"fmt"
)

type littleGirl struct{
	Name string
	Age int
}


func(this littleGirl) changeName(name string){
	fmt.Println(name)
}

func main(){
	little := littleGirl{Name:"Rose", Age:1}

	little = nil
	little.changeName("yoyo")
	fmt.Println(little)
}

Отвечать:

不能编译通过,显示"cannot use nil as type littleGirl in assignment"

В Go методы могут принимать нулевые указатели в качестве приемников, а функции могут принимать нулевые указатели в качестве параметров. И в приведенном выше кодеlittleGirlне является типом указателя, измените его на*littleGirl, то переменнаяlittleназначить как&littleGirl{Name:"Rose", Age:1}Его можно скомпилировать и передать. Кроме того, когда nil является допустимым нулевым значением для объекта, такого как карта или фрагмент, он компилируется и работает нормально.

Форматирование времени в Голанге

отличается от PHPdate("Y-m-d H:i:s", time()), формат Golang очень странный, вы не можете использовать такие вещи, какY-m-d H:i:sчто-то, но использовать2006-01-02 15:04:05Формат этого времени, пожалуйста, помните это время, говорят, что это время рождения Голанга.

time := time.Now()

time.Format("20060102") //相当于Ymd

time.Format("2006-01-02")//相当于Y-m-d

time.Format("2006-01-02 15:04:05")//相当于Y-m-d H:i:s

time.Format("2006-01-02 00:00:00")//相当于Y-m-d 00:00:00

Для получения более интересного контента, пожалуйста, обратите внимание на мой публичный аккаунт WeChat.互联网技术窝Или добавьте WeChat для обсуждения и общения: