Repository URL to install this package:
|
Version:
1.6.6 ▾
|
A slice (also named list) is a dynamically-sized, flexible view into the elements of an array. Slices are one of the most commonly used data structures in XGo, providing efficient and convenient ways to work with sequences of elements.
Note: In XGo, the terms slice and list are identical and refer to the same data structure. The term "slice" comes from Go's terminology, while "list" aligns with Python's naming convention.
A slice consists of three components:
Unlike arrays which have a fixed size, slices can grow and shrink dynamically, making them ideal for most collection use cases.
XGo provides multiple ways to create slices: using slice literals for quick initialization with data, using the make function for more control over slice types and capacity, and slicing existing arrays or slices.
In XGo, you can create slices using square brackets []:
a := [1, 2, 3] // []int b := [1, 2, 3.4] // []float64 c := ["Hi"] // []string d := ["Hi", 10] // []any - mixed types e := [] // []any - empty slice
When using the := syntax without explicit type declaration, XGo automatically infers the complete slice type []ElementType based on the literal values provided.
Type Inference Rules
any.[]: Inferred as []any by default for maximum flexibility.You can also explicitly specify the slice type to override automatic type inference:
// Explicit type declaration var a []float64 = [1, 2, 3] // Values converted to float64 var c []any = ["x", 1, true] // Explicit any type
When a type is explicitly declared, the literal values are converted to match the declared type.
makeUse make when you need an empty slice or want to optimize performance by pre-allocating capacity.
make Syntax// Create slice with specified length (initialized to zero values) s1 := make([]int, 5) // [0, 0, 0, 0, 0] s2 := make([]string, 3) // ["", "", ""] // Access and modify s1[0] = 100 s1[2] = 300 echo s1 // Output: [100 0 300 0 0]
For performance optimization, you can specify both length and capacity:
// Create slice with length 0 and capacity 100 s := make([]int, 0, 100) // This doesn't limit the slice size, but helps reduce allocations for i := 0; i < 150; i++ { s <- i } echo len(s) // Output: 150 echo cap(s) // Output: likely > 150
The capacity hint doesn't limit the slice's size but helps the runtime allocate memory more efficiently when you know approximately how many elements you'll add.
make vs LiteralsUse slice literals ([]) when:
Use slice literals with explicit type (var s []T = []) when:
Use make when:
makeYou can create new slices by slicing existing arrays or slices using the range syntax [start:end]:
arr := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // Basic slicing slice1 := arr[2:5] // [3, 4, 5] - from index 2 to 5 (exclusive) slice2 := arr[:3] // [1, 2, 3] - from start to index 3 slice3 := arr[5:] // [6, 7, 8, 9, 10] - from index 5 to end slice4 := arr[:] // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - full slice (shallow copy)
Important: Slices created this way share the same underlying array. Modifying one slice may affect others:
arr := [1, 2, 3, 4, 5] slice1 := arr[1:4] // [2, 3, 4] slice2 := arr[2:5] // [3, 4, 5] slice1[1] = 100 // Modifies the shared underlying array echo slice1 // Output: [2 100 4] echo slice2 // Output: [100 4 5] - also affected! echo arr // Output: [1 2 100 4 5] - original array modified
You can directly modify elements at specific indexes:
nums := [1, 2, 3, 4, 5] nums[0] = 100 nums[2] = 300 echo nums // Output: [100 2 300 4 5]
XGo provides two ways to append elements to slices: the <- operator and the append built-in function.
<- OperatorThe <- operator provides an intuitive way to append elements:
nums := [1, 2, 3] nums <- 4 // Append single element nums <- 5, 6, 7 // Append multiple elements more := [8, 9, 10] nums <- more... // Append another slice echo nums // Output: [1 2 3 4 5 6 7 8 9 10]
append FunctionThe append function returns a new slice with elements added or removed:
// Adding elements nums := [1, 2, 3] nums = append(nums, 4) // Append single element nums = append(nums, 5, 6, 7) // Append multiple elements more := [8, 9, 10] nums = append(nums, more...) // Append another slice echo nums // Output: [1 2 3 4 5 6 7 8 9 10]
Important: The append function returns a new slice, so you must assign the result back to a variable.
appendThe append function can also remove consecutive elements by concatenating slices before and after the range to remove:
nums := [1, 2, 3, 4, 5] // Remove element at index 2 (value 3) nums = append(nums[:2], nums[3:]...) echo nums // Output: [1 2 4 5] // Remove multiple consecutive elements (indices 1-2) nums = [1, 2, 3, 4, 5] nums = append(nums[:1], nums[3:]...) echo nums // Output: [1 4 5]
This pattern uses slice notation to select everything before the removal range (nums[:start]) and everything after it (nums[end:]), then concatenates them together. This effectively removes the elements in the slice nums[start:end].
Indexes start from 0. Valid indexes range from 0 to len(slice) - 1:
nums := [10, 20, 30, 40, 50] echo nums[0] // 10 - first element echo nums[1] // 20 - second element echo nums[4] // 50 - last element
Note: Negative indexing is not supported. Using an index outside the valid range will cause a runtime error.
You can get the length and capacity of a slice using the len and cap functions:
nums := [1, 2, 3, 4, 5] echo len(nums) // 5 - number of elements echo cap(nums) // 5 - capacity (may be larger)
You can extract portions of a slice using the range syntax:
nums := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] echo nums[2:5] // [2 3 4] - from index 2 to 5 (exclusive) echo nums[:3] // [0 1 2] - from start to index 3 echo nums[5:] // [5 6 7 8 9] - from index 5 to end echo nums[:] // [0 1 2 3 4 5 6 7 8 9] - full slice (shallow copy)
Remember: Sub-slices share the underlying array with the original slice. See "Creating Slices from Arrays or Slices" for details on this behavior.
XGo provides multiple ways to iterate over slices using for loops:
nums := [10, 20, 30, 40, 50] for i, v in nums { echo "Index:", i, "Value:", v }
nums := [10, 20, 30, 40, 50] for v in nums { echo v }
nums := [10, 20, 30, 40, 50] for i, _ in nums { echo "Index:", i }
List comprehensions provide a concise and expressive way to create new lists by transforming or filtering existing sequences. They follow a syntax similar to Python's list comprehensions.
The general form of a list comprehension is:
[expression for vars in iterable]
This creates a new list where each element from the iterable is transformed by the expression.
// Square all numbers numbers := [1, 2, 3, 4, 5] squares := [v * v for v in numbers] echo squares // Output: [1 4 9 16 25] // Convert to strings words := ["hello", "world"] upper := [v.toUpper for v in words] echo upper // Output: ["HELLO" "WORLD"] // Extract from index-value pairs doubled := [v * 2 for i, v in numbers] echo doubled // Output: [2 4 6 8 10]
// Generate sequence nums := [i for i in 1:11] echo nums // Output: [1 2 3 4 5 6 7 8 9 10] // With transformation evens := [i * 2 for i in :5] echo evens // Output: [0 2 4 6 8] // With step odds := [i for i in 1:10:2] echo odds // Output: [1 3 5 7 9]
Add an if clause to filter elements:
[expression for vars in iterable if condition]
numbers := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // Only even numbers evens := [v for v in numbers if v % 2 == 0] echo evens // Output: [2 4 6 8 10] // Only numbers greater than 5 large := [v for v in numbers if v > 5] echo large // Output: [6 7 8 9 10] // Filter and transform evenSquares := [v * v for v in numbers if v % 2 == 0] echo evenSquares // Output: [4 16 36 64 100]
numbers := [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] // Elements at even indices evenIndexValues := [v for i, v in numbers if i % 2 == 0] echo evenIndexValues // Output: [10 30 50 70 90]
List comprehensions can be nested to work with multi-dimensional data:
// Flatten a 2D list matrix := [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened := [num for row in matrix for num in row] echo flattened // Output: [1 2 3 4 5 6 7 8 9] // Create multiplication table table := [[i * j for j in 1:6] for i in 1:6] echo table // Output: [[1 2 3 4 5] [2 4 6 8 10] [3 6 9 12 15] [4 8 12 16 20] [5 10 15 20 25]] // Extract diagonal elements diagonal := [matrix[i][i] for i in :len(matrix)] echo diagonal // Output: [1 5 9]
Use list comprehensions when:
Use traditional loops when:
// Good use of comprehension squares := [x * x for x in :10] // Better as a traditional loop (side effects, complex logic) results := [] for x in :10 { result := complexCalculation(x) if result > threshold { results <- result updateGlobalState(result) } }
nums := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] evens := [] for v in nums { if v % 2 == 0 { evens <- v } } echo evens // Output: [2 4 6 8 10]
nums := [1, 2, 3, 4, 5] squared := [] for v in nums { squared <- v * v } echo squared // Output: [1 4 9 16 25]
nums := [10, 20, 30, 40, 50] target := 30 found := false index := -1 for i, v in nums { if v == target { found = true index = i break } } if found { echo "Found", target, "at index", index } else { echo target, "not found" }
nums := [1, 2, 3, 4, 5] reversed := [] for i := len(nums) - 1; i >= 0; i-- { reversed <- nums[i] } echo reversed // Output: [5 4 3 2 1]
nums := [1, 2, 2, 3, 3, 3, 4, 5, 5] unique := [] seen := {} for v in nums { if !seen[v] { unique <- v seen[v] = true } } echo unique // Output: [1 2 3 4 5]
a := [1, 2, 3] b := [4, 5, 6] c := [7, 8, 9] merged := [] merged <- a... merged <- b... merged <- c... echo merged // Output: [1 2 3 4 5 6 7 8 9]
nums := [1, 2, 3, 4, 5] sum := 0 for v in nums { sum += v } echo sum // Output: 15
nums := [34, 12, 67, 23, 89, 45] max := nums[0] min := nums[0] for v in nums { if v > max { max = v } if v < min { min = v } } echo "Max:", max // Output: 89 echo "Min:", min // Output: 12
nums := [10, 20, 30, 40, 50] target := 30 contains := false for v in nums { if v == target { contains = true break } } echo contains // Output: true
nums := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] evens := [] odds := [] for v in nums { if v % 2 == 0 { evens <- v } else { odds <- v } } echo evens // Output: [2 4 6 8 10] echo odds // Output: [1 3 5 7 9]
nested := [[1, 2], [3, 4], [5, 6]] flat := [] for subslice in nested { flat <- subslice... } echo flat // Output: [1 2 3 4 5 6]
stack := [] // Push elements stack <- 1 stack <- 2 stack <- 3 echo stack // Output: [1 2 3] // Pop element if len(stack) > 0 { top := stack[len(stack) - 1] stack = stack[:len(stack) - 1] echo "Popped:", top // Output: Popped: 3 echo stack // Output: [1 2] }
queue := [] // Enqueue elements queue <- 1 queue <- 2 queue <- 3 echo queue // Output: [1 2 3] // Dequeue element if len(queue) > 0 { front := queue[0] queue = queue[1:] echo "Dequeued:", front // Output: Dequeued: 1 echo queue // Output: [2 3] }
nums := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] windowSize := 3 for i := 0; i <= len(nums) - windowSize; i++ { window := nums[i:i + windowSize] echo "Window:", window } // Output: // Window: [1 2 3] // Window: [2 3 4] // Window: [3 4 5] // ...
// Group items by category items := ["apple", "banana", "carrot", "date", "eggplant"] groups := make(map[string][]string) for item in items { firstLetter := item[0:1] groups[firstLetter] <- item } // Access grouped data for category, itemList in groups { echo "Category:", category for item in itemList { echo " -", item } }
make([]T, 0, size) to avoid multiple reallocationslen(slice) and cap(slice): These are the recommended ways to get length and capacity[0, len(slice)-1]<- operator for appending: It's more concise and idiomatic in XGocopy or manual copyingWhen a slice's capacity is exceeded during append operations, XGo allocates a new underlying array with increased capacity:
s := [] echo len(s), cap(s) // Output: 0 0 s <- 1 echo len(s), cap(s) // Output: 1 1 s <- 2 echo len(s), cap(s) // Output: 2 2 s <- 3 echo len(s), cap(s) // Output: 3 4 (capacity doubled) s <- 4, 5 echo len(s), cap(s) // Output: 5 8 (capacity doubled again)
The exact growth strategy may vary, but typically capacity doubles when exceeded.
Pre-allocating capacity avoids multiple reallocations:
// Inefficient - multiple reallocations inefficient := [] for i := 0; i < 1000; i++ { inefficient <- i } // Efficient - single allocation efficient := make([]int, 0, 1000) for i := 0; i < 1000; i++ { efficient <- i }
When creating a small slice from a large slice, the underlying array is still retained:
// May cause memory leak func getFirstThree(data []int) []int { return data[:3] // Still references the entire underlying array } // Better approach - create independent slice func getFirstThree(data []int) []int { result := make([]int, 3) copy(result, data[:3]) return result }
nums := [1, 2, 3] // This will cause a runtime error // echo nums[10] // Error: index out of range // Always check bounds index := 10 if index >= 0 && index < len(nums) { echo nums[index] } else { echo "Index out of bounds" }
nums := [1, 2, 3, 4, 5] // This is NOT valid in XGo // echo nums[-1] // Error: invalid slice index // To access last element, use: echo nums[len(nums) - 1] // Output: 5
a := [1, 2, 3] b := a // b references same underlying array b[0] = 100 echo a // Output: [100 2 3] - a is also modified! // To avoid this, make a copy c := make([]int, len(a)) copy(c, a) c[0] = 200 echo a // Output: [100 2 3] - a is not affected
// Careful with slice of slices matrix := [] row := [1, 2, 3] matrix <- row matrix <- row // Both rows reference the same underlying array! row[0] = 100 echo matrix // Output: [[100 2 3] [100 2 3]] - both rows are modified! // Better approach - create independent rows matrix := [] matrix <- [1, 2, 3] matrix <- [1, 2, 3] // Each row is independent
// Avoid this - may cause unexpected behavior nums := [1, 2, 3, 4, 5] for i, v in nums { if v % 2 == 0 { nums <- v * 2 // Modifying during iteration - risky! } } // Better approach - create new slice result := [] for v in nums { if v % 2 == 0 { result <- v * 2 } else { result <- v } }
XGo's slices provide a powerful and flexible way to work with sequences of elements. Key features include:
[] for concise slice creation<- operator or append function for adding elementsBy understanding these features and following best practices, you can write efficient and maintainable code that leverages the full power of XGo's slice type.