Bonne façon d'initialiser une tranche vide


227

Pour déclarer une tranche vide, avec une taille non fixe, il vaut mieux faire:

mySlice1 := make([]int, 0)

ou:

mySlice2 := []int{}

Je me demande simplement laquelle est la bonne façon.


2
Vous dites "taille non fixe", mais les tranches n'ont jamais une taille fixe. Sauf si vous voulez dire avec une capacité nulle. Remarque, si vous avez une idée / une supposition / un indice de la capacité dont vous pourriez avoir besoin, l'utilisation de la version à trois arguments est bonne. Par exemple pour construire une tranche de clés de carte:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
Dave C

Réponses:


272

Les deux alternatives que vous avez données sont sémantiquement identiques, mais l'utilisation make([]int, 0)entraînera un appel interne à runtime.makeslice (Go 1.14).

Vous avez également la possibilité de le laisser avec une nilvaleur:

var myslice []int

Comme écrit sur le blog de Golang.org :

une tranche nulle est fonctionnellement équivalente à une tranche de longueur nulle, même si elle ne pointe vers rien. Il a une longueur nulle et peut être ajouté avec une allocation.

Une niltranche entrera cependant json.Marshal()dans "null"alors qu'une tranche vide entrera en "[]"mars, comme indiqué par @farwayer.

Aucune des options ci-dessus ne provoquera d'allocation, comme l'a souligné @ArmanOrdookhani.


4
Mentionnez également sur le wiki github.com/golang/go/wiki/…
Grzegorz

106
Attention: json.Marshal()reviendra nullpour var myslice []intet []pour la tranche initialiséemyslice := []int{}
farwayer

10
Aussi soyez prudent: reflect.DeepEqualfait une distinction entre les tranches nil et tranches non nul: a := []int{}, var b []int,reflect.DeepEqual(a, b) // returns false
asgaines

1
Pourquoi pensez-vous qu'il ferait une allocation? Le plafond est nul, donc rien n'est alloué. Tous les pointeurs vers des objets de longueur nulle pointent vers le même emplacement en mémoire: play.golang.org/p/MPOKKl_sYvw
Arman Ordookhani

1
@ArmanOrdookhani Vous avez raison. Je l'ai essayé et j'ai également découvert que j'avais tort avec mon hypothèse sur des instructions de montage identiques. Fixé!
ANisus

65

Ils sont équivalents. Voir ce code:

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

Production:

mySlice1 0
mySlice2 0

Les deux tranches ont une 0capacité, ce qui implique que les deux tranches ont une 0longueur (ne peut pas être supérieure à la capacité), ce qui implique que les deux tranches n'ont aucun élément. Cela signifie que les 2 tranches sont identiques dans tous les aspects.

Voir des questions similaires:

Quel est l'intérêt d'avoir une tranche nulle et une tranche vide dans le golang?

tranches nulles vs tranches non nulles vs tranches vides en langue Go


46

En complément de la réponse de @ANisus ...

Voici quelques informations du livre "Go in action" , qui, je pense, méritent d'être mentionnées:

Différence entre nil& emptytranches

Si nous pensons à une tranche comme celle-ci:

[pointer] [length] [capacity]

puis:

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

tranche nulle

Ils sont utiles lorsque vous souhaitez représenter une tranche qui n'existe pas, par exemple lorsqu'une exception se produit dans une fonction qui renvoie une tranche.

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

tranche vide

Les tranches vides sont utiles lorsque vous souhaitez représenter une collection vide, par exemple lorsqu'une requête de base de données ne renvoie aucun résultat.

// 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{}

Peu importe si vous utilisez une tranche nulle ou une tranche vide, la fonctions intégrées append, lenet le captravail même.


Exemple de terrain de jeu :

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))

}

impressions:

true 0 0
false 0 0

Pouvons-nous obtenir l'adresse de la tranche vide en une seule étape en utilisant make?
Simin Jie

Si nous jetons un oeil à la signature de la fonction , makene semble pas retourner l'adresse. Je crois que vous ne pouvez pas le faire en une seule étape.
tgogos

13

La tranche vide et la tranche nulle sont initialisées différemment dans 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

Comme pour les trois tranches, len et cap sont à 0.


make([]int, 0)est le meilleur parce que Jetbrains GoLand ne se plaint pas qu'il soit "inutile" comme il le fait dans le cas de []int{}. Ceci est utile pour écrire des tests unitaires.
Andrzej Rehmann
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.