Maneira correta de inicializar fatia vazia


227

Para declarar uma fatia vazia, com um tamanho não fixo, é melhor fazer:

mySlice1 := make([]int, 0)

ou:

mySlice2 := []int{}

Apenas querendo saber qual é o caminho correto.


2
Você diz "tamanho não fixo", mas as fatias nunca têm um tamanho fixo. A menos que você queira dizer com capacidade zero. Observe que, se você tiver uma ideia / sugestão / sugestão de qual capacidade poderá precisar, usar a versão de três argumentos é bom. Por exemplo, para criar uma fatia das chaves do mapa:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
Dave C

1
Possível duplicata de Declarar fatia ou fazer fatia?
usuário

Respostas:


272

As duas alternativas que você forneceu são semanticamente idênticas, mas o uso make([]int, 0)resultará em uma chamada interna para o tempo de execução.makeslice (Go 1.14).

Você também tem a opção de deixá-lo com um nilvalor:

var myslice []int

Conforme escrito no blog Golang.org :

uma fatia nula é funcionalmente equivalente a uma fatia de comprimento zero, mesmo que não aponte para nada. Tem comprimento zero e pode ser anexado a, com alocação.

A nilfatia vai, porém, json.Marshal()em"null" enquanto uma fatia vazia será inserida "[]", como apontado por @farwayer.

Nenhuma das opções acima causará alocação, como apontado por @ArmanOrdookhani.


4
Mencione também no wiki github.com/golang/go/wiki/…
Grzegorzur

106
Seja cautela: json.Marshal()vai voltar nullpara var myslice []inte []para a fatia inicializadomyslice := []int{}
farwayer

10
Também deve ter cuidado: reflect.DeepEqualfaz uma distinção entre fatias de Nil e fatias não-nil: a := []int{}, var b []int,reflect.DeepEqual(a, b) // returns false
asgaines

1
Por que você acha que isso faria uma alocação? O limite é zero, portanto nada é alocado. Todos os ponteiros para comprimento zero apontam para o mesmo local na memória: play.golang.org/p/MPOKKl_sYvw
Arman Ordookhani em

1
@ArmanOrdookhani Você está correto. Eu tentei e também descobri que estava errado ao supor instruções de montagem idênticas. Fixo!
ANisus 21/04

65

Eles são equivalentes. Veja este código:

mySlice1 := make([]int, 0)
mySlice2 := []int{}
fmt.Println("mySlice1", cap(mySlice1))
fmt.Println("mySlice2", cap(mySlice2))

Resultado:

mySlice1 0
mySlice2 0

Ambas as fatias têm 0capacidade, o que implica que ambas as fatias tenham0 comprimento (não pode ser maior que a capacidade), o que implica que ambas as fatias não possuem elementos. Isso significa que as duas fatias são idênticas em todos os aspectos.

Veja perguntas semelhantes:

Qual é o sentido de ter fatia nula e fatia vazia em golang?

fatias nulas vs fatias não nulas vs fatias vazias no idioma Go


46

Como complemento ao @ANisus ' resposta do ...

abaixo estão algumas informações do "Entrar em ação" livro , que acho que vale a pena mencionar:

Diferença entre nil&empty fatias

Se pensarmos em uma fatia como esta:

[pointer] [length] [capacity]

então:

nil slice:   [nil][0][0]
empty slice: [addr][0][0] // points to an address

nenhuma fatia

Eles são úteis quando você deseja representar uma fatia que não existe, como quando ocorre uma exceção em uma função que retorna uma fatia.

// Create a nil slice of integers.
var slice []int

fatia vazia

Fatias vazias são úteis quando você deseja representar uma coleção vazia, como quando uma consulta ao banco de dados retorna zero resultados.

// Use make to create an empty slice of integers.
slice := make([]int, 0)

// Use a slice literal to create an empty slice of integers.
slice := []int{}

Independentemente de saber se você está usando uma fatia nulo ou uma fatia vazia, o built-in funções append, lene captrabalho da mesma.


Exemplo de playground :

package main

import (
    "fmt"
)

func main() {

    var nil_slice []int
    var empty_slice = []int{}

    fmt.Println(nil_slice == nil, len(nil_slice), cap(nil_slice))
    fmt.Println(empty_slice == nil, len(empty_slice), cap(empty_slice))

}

impressões:

true 0 0
false 0 0

Podemos obter o endereço da fatia vazia em uma etapa usando make?
precisa

Se dermos uma olhada na assinatura da função , makenão parece retornar o endereço. Eu acredito que você não pode fazer isso em uma única etapa.
Tgogos 16/07/19

13

Fatia vazia e nula são inicializadas de maneira diferente no Go:

var nilSlice []int 
emptySlice1 := make([]int, 0)
emptySlice2 := []int{}

fmt.Println(nilSlice == nil)    // true
fmt.Println(emptySlice1 == nil) // false
fmt.Println(emptySlice2 == nil) // false

Quanto às três fatias, len e cap são 0.


make([]int, 0)é o melhor porque o Jetbrains GoLand não se queixa de ser "desnecessário", como no caso de []int{}. Isso é útil para escrever testes de unidade.
Andrzej Rehmann
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.