Skip to content

Instantly share code, notes, and snippets.

@takatoshiono
Last active December 28, 2022 00:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takatoshiono/3b54fdef1980e66e7b8f6766cc03e405 to your computer and use it in GitHub Desktop.
Save takatoshiono/3b54fdef1980e66e7b8f6766cc03e405 to your computer and use it in GitHub Desktop.
CopyDigits function ref
package main
// ref: https://blog.golang.org/go-slices-usage-and-internals
// 1234 <-- digits
import (
"fmt"
"io/ioutil"
"regexp"
)
var digitRegexp = regexp.MustCompile("[0-9]+")
func CopyDigits(filename string) []byte {
b, _ := ioutil.ReadFile(filename)
b = digitRegexp.Find(b)
return append([]byte{}, b...)
}
func main() {
digits := CopyDigits("./copy-digits.go")
fmt.Println(digits)
}
@takatoshiono
Copy link
Author

takatoshiono commented Aug 25, 2016

$ go run copy-digits.go
[49 50 51 52]

@takatoshiono
Copy link
Author

https://blog.golang.org/go-slices-usage-and-internalsA more concise version of this function could be constructed by using append. This is left as an exercise for the reader. というのをやってみた

@gkotian
Copy link

gkotian commented Nov 24, 2019

Thanks, that was helpful 👍

@JonnyCBB
Copy link

This was very helpful. Thank you.

@kwangh
Copy link

kwangh commented Mar 20, 2021

Thank you very much. This helped me understand how slice append works!

@1Mark
Copy link

1Mark commented Nov 6, 2022

Is there a way to show how much memory has been saved vs the original code?

@telemachus
Copy link

telemachus commented Dec 14, 2022

@1Mark I may be wrong, but I think you can see by checking the capacity of the slice. Here's an example that focuses on that.

package main

import (
	"fmt"
	"log"
	"os"
)

const sAndS = "s-and-s.txt"

func main() {
	data, err := os.ReadFile(sAndS)
	if err != nil {
		log.Fatalf("cannot open 's-and-s.txt': %v\n", err)
	}

	fmt.Println("Before slicing:")
	fmt.Printf("\tlen(data) = %d; cap(data) = %d\n", len(data), cap(data))

	data = data[0:4]
	fmt.Println("After data = data[0:4]:")
	fmt.Printf("\tlen(data) = %d; cap(data) = %d\n", len(data), cap(data))

	data = append([]byte{}, data[0:4]...)
	fmt.Println("After data = append([]byte{}, data[0:4]...):")
	fmt.Printf("\tlen(data) = %d; cap(data) = %d\n", len(data), cap(data))
}

I used it on a plaintext version of a book, and the output shows how many bytes the original file has and how many bytes different slices have access to.

$ wc -c s-and-s.txt
  712928 s-and-s.txt
$ ./append
Before slicing:
	len(data) = 712928; cap(data) = 712929
After data = data[0:4]:
	len(data) = 4; cap(data) = 712929
After data = append([]byte{}, data[0:4]...):
	len(data) = 4; cap(data) = 8

You can see that reassigning with a slice expression reduces the length, but the capacity is still as large as the whole file (712929 bytes). But if you use append and force it to create a new backing array, the result is 8 bytes rather than 712929.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment