Reference type confusing in Go language - go

I tried to make Trie data structures by Go Language, but somehow it stuck with References problem,
Here it is. http://play.golang.org/p/ASSGF5Oe9R
// Package main provides ...
package main
import "fmt"
type RootTrie []Trie
type Trie struct {
subtrie []Trie
index byte
}
func (trie *Trie) Insert(data string) *Trie {
if data != "" {
if trie.index == 0 {
trie.index = data[0]
}
if next := trie.containsIndex(data[1:]); next != nil {
//Problem Point
fmt.Println(string(data[1]), "found follwing", string(data[0]))
next.Insert(data[1:])
} else {
nt := &Trie{}
trie.subtrie = append(trie.subtrie, *nt.Insert(data[1:]))
}
}
return trie
}
func (trie *Trie) containsIndex(next string) *Trie {
if next != "" {
for _, st := range trie.subtrie {
if st.index == next[0] {
return &st
}
}
}
return nil
}
func main() {
t := &Trie{}
t = t.Insert("hanyang")
fmt.Println("result:", t)
t = t.Insert("hanyKk")
fmt.Println("result:", t)
t.Insert("hanyK")
}
The following problems happen in second "Insert",
the where I put, //Problem Point
I made containsIndex method for searching next linked trie, and it searched well actually.
But when I updated next property which containsIndex given, its not affected its mother struct trie though.
What I don't understand is I gave it reference type when returning containsIndex, but its still
act liked 'value copied', Why does it not affected its mother structure(trie)?
Thanks!

The problem is in method containsIndex. Golang range by default creates copy each element in slice and assigns copy of this value to st (in your example). Usually to preserve reference to element in slice you should use original slice and its index. In you case method containsIndex should look something like this:
func (trie *Trie) containsIndex(next string) *Trie {
if next != "" {
for i, st := range trie.subtrie {
if st.index == next[0] {
return &trie.subtrie[i]
}
}
}
return nil
}

Related

Appending to pointer slice

Go is my first programming language and I am trying to learn about pointers by writing a program that organizes information based on taxonomies. I'm having some trouble understanding how to append to a pointer slice.
type List struct {
Taxonomies []Taxonomy
}
func (l *List) Add(t Taxonomy) {
var exists bool
var existing *Taxonomy
for _, taxonomy := range l.Taxonomies {
if taxonomy.Name == t.Name {
exists = true
existing = &taxonomy
}
}
if exists {
for _, term := range t.Data {
termExists := false
for _, existingTerm := range existing.Data {
if existingTerm.Name == term.Name {
termExists = true
break
}
}
if termExists {
continue
}
(*existing).Data = append((*existing).Data, term)
}
} else {
l.Taxonomies = append(l.Taxonomies, t)
}
}
type Taxonomy struct {
Name string
Data []Term
}
type Term struct {
Name, Link string
}
I think the problem is toward the bottom, this line:
(*existing).Data = append((*existing).Data, term)
By following the code in a debugger, I can see that the taxonomy stored in the "existing" variable is being updated when the append occurs, but the data is not updated in the actual List.
Can anyone tell me where I am going wrong?
l.Taxonomies is a []Taxonomy, so the taxonomy value is going to be a copy of the element, and changes to that copy will not be reflected in the original List value.
You can iterate using the index to avoid copying the value
for i := range l.Taxonomies {
if l.Taxonomies[i].Name == t.Name {
exists = true
existing = &l.Taxonomies[i]
}
}
However that still leaves the possibility of copying the data passed to methods like Append. Instead it's probably better to use pointers throughout:
type List struct {
Taxonomies []*Taxonomy
}
func (l *List) Add(t *Taxonomy) {
...

appending strings to a slice recursively causes out of memory error in golang

I'm trying to parse an HTML page and print its links.
I'm going over the parsed Html tree recursively adding links to a slice of strings.
I'm missing something out as I get out of memory error
here is my code:
package parser
import (
"errors"
"io"
"golang.org/x/net/html"
)
//URLParser returns all the urls inside a html page
type URLParser struct {
}
//GetURLS returns all
func (URLParser) GetURLS(htmlInput io.Reader) (*[]string, error) {
result := []string{}
htmlRoot, err := html.Parse(htmlInput)
//result := make([]string, 1000)
if err != nil {
parserError := errors.New("html parser failed with error" + err.Error())
return nil, parserError
}
finalResult := traverseHTMLTree(htmlRoot, &result)
return finalResult, nil
}
func traverseHTMLTree(node *html.Node, result *[]string) *[]string {
if node == nil {
return nil
}
if isLinkElement(node) {
currlink, shouldUse := getURLAttrb(node.Attr)
if shouldUse {
*result = append(*result, currlink)
}
}
for currNode := node.FirstChild; currNode != nil; currNode = currNode.NextSibling {
currRest := traverseHTMLTree(currNode, result)
if currRest != nil {
*result = append(*currRest, *result...)
}
}
return result
}
func getURLAttrb(attr []html.Attribute) (string, bool) {
for i := 0; i < len(attr); i++ {
if attr[i].Key == "href" {
return attr[i].Val, true
}
}
return "", false
}
func isLinkElement(node *html.Node) bool {
if node.Type == html.ElementNode {
if node.Data == "a" {
return true
}
}
return false
}
When just trying to print the links to stdout it works perfectly, so it got to be something with the way I handle the slice..
For each node in the HTML tree, you're adding the contents of the results array to itself, recursively. That should grow pretty quickly.
Note that when you check if isLinkElement, you add the item to the result list.
Then for each element of the html tree, you append the contents of the results array to itself, doubling it.
You're passing a pointer to a slice. You're effectively using a single slice for the whole program, and keep adding to it. What you're returning from the traverseHTMLTree is the same slice, not a copy of it. So it keeps growing.
One way to fix it is: do not pass the pointer to the slice. Pass the current slice, update it, and return the new slice.

Implement generic linked list in golang which disallows different types in the same linkedlist

I want to make a linked list which can hold the values of any type but the linked list must hold values of any one type only.
In general when I am using interfaces for achieving this - any type which implements the interface for the node can be added to the linked list.
I have written an implementation for this where whenever a new key is added to the linked list, the type of the key is checked against the type of the key at the head. I want to understand if this is the correct way of implementing it or is there a better way of doing it.
package main
import (
"errors"
"fmt"
"reflect"
"strings"
)
type MyNode struct {
value int
}
func (node *MyNode) PrintValue() {
fmt.Printf(" %d ", node.value)
}
type llNode struct {
key llNodeInterface
next *llNode
llNodeType reflect.Type
}
type llNodeInterface interface {
PrintValue()
}
type ComplexNode struct {
realValue int
imageValue int
}
func (node *ComplexNode) PrintValue() {
fmt.Printf(" %d + i%d", node.realValue, node.imageValue)
}
// Student type.
type Student struct {
name string
age int
}
// Student implements the PrintValue function - thus llNodeInterface is implemented.
func (node *Student) PrintValue() {
fmt.Printf("Name: %s | Age : %d ", node.name, node.age)
}
// Function which will check the of the new node before adding to the linked
// list. It checks the type of the new key against the type of the key in the
// head. If both are equal then it proceed else return error.
func (head *llNode) AddBeforeHeadTypeCheck(passedKey llNodeInterface) error {
if head.key == nil {
head.key = passedKey
head.llNodeType = reflect.TypeOf(head.key)
} else {
typeOfPassedKey := reflect.TypeOf(passedKey)
if typeOfPassedKey != head.llNodeType {
fmt.Printf("\nUnsupported type for the type %T", passedKey)
return errors.New("Type mistmatch")
}
temp := llNode{key: head.key, next: head.next}
head.key = passedKey
head.next = &temp
}
return nil
}
// Function which will not check the types and will simply add the new node to
// the linked list. Thus linked list will be able to have nodes of multiple
// types.
func (head *llNode) AddBeforeHead(passedKey llNodeInterface) {
if head.key == nil {
head.key = passedKey
head.llNodeType = reflect.TypeOf(head.key)
} else {
temp := llNode{key: head.key, next: head.next}
head.key = passedKey
head.next = &temp
}
}
func (head *llNode) Init() {
head.key = nil
head.next = nil
head.llNodeType = nil
}
// Print the linked list.
func (head *llNode) DisplayLL() {
temp := head
fmt.Printf("\n%s", strings.Repeat("#", 80))
fmt.Printf("\nPrinting the linked list\n")
for {
if temp.key == nil {
fmt.Println("Linked list is empty")
break
} else {
fmt.Printf("\n %T %v ", temp.key, temp.key)
key := temp.key
key.PrintValue()
if temp.next == nil {
break
} else {
temp = temp.next
}
}
}
fmt.Printf("\n%s", strings.Repeat("#", 80))
fmt.Printf("\n\n")
}
func testWithMixedType() {
head := llNode{}
head.Init()
for i := 1; i < 10; i++ {
temp := &ComplexNode{i, i * 10}
head.AddBeforeHeadTypeCheck(temp)
}
temps := &Student{"rishi", 20}
head.AddBeforeHeadTypeCheck(temps) // Will give error.
head.DisplayLL()
}
func testWithComplexNumber() {
head := llNode{}
head.Init()
for i := 1; i < 10; i++ {
temp := &ComplexNode{i, i * 10}
head.AddBeforeHeadTypeCheck(temp)
}
}
func main() {
testWithComplexNumber()
testWithMixedType()
}
The code is working fine - but I want to understand if there is a better or different way of doing this.
Also - what is the performance impact of the current checking of types using the reflect package. Is there a different way of achieving the same thing.
Unsupported type for the type *main.Student
Unsupported type for the type *main.Student
################################################################################
Printing the linked list
*main.ComplexNode &{9 90} 9 + i90
*main.ComplexNode &{8 80} 8 + i80
*main.ComplexNode &{7 70} 7 + i70
*main.ComplexNode &{6 60} 6 + i60
*main.ComplexNode &{5 50} 5 + i50
*main.ComplexNode &{4 40} 4 + i40
*main.ComplexNode &{3 30} 3 + i30
*main.ComplexNode &{2 20} 2 + i20
*main.ComplexNode &{1 10} 1 + i10
################################################################################
Good news, starting from Go 1.18, Generics are now supported in Go.
Following the example from the question, here is a simplified LinkedList using Generics. You can tinker with it at the playground here.
package main
import "fmt"
type MyNode[T any] struct {
next *MyNode[T]
value T
}
type MyLinkedList[T any] struct {
head *MyNode[T]
tail *MyNode[T]
}
func (list *MyLinkedList[T]) Add(t T) *MyLinkedList[T] {
// create node
node := &MyNode[T]{nil, t}
// if first node in list
if list.head == nil {
list.head = node
list.tail = node
} else {
list.tail.next = node
list.tail = list.tail.next
}
return list
}
func (list *MyLinkedList[T]) AddBeforeHead(t T) *MyLinkedList[T] {
node := &MyNode[T]{nil, t}
if list.head != nil {
node.next = list.head
list.head = node
} else {
// make head
list.head = node
list.tail = node
}
return list
}
// display the list
func DisplayList[T any](list *MyLinkedList[T]) string {
var out string = ""
iter := list.head
for iter != nil {
out += fmt.Sprintf("%v -> ", iter.value)
iter = iter.next
}
return out
}
func (list *MyLinkedList[T]) Display() string {
return DisplayList(list)
}
// for printing node value
// you could also implement Stringer
// but this is besides the point, you can ignore
func (node *MyNode[T]) String() string {
return fmt.Sprintf("<MyNode: %v>", node.value)
}
// helper func: create list from array
func CreateLinkedList[T any](arr []T) *MyLinkedList[T] {
list := &MyLinkedList[T]{}
for _, v := range arr {
list.Add(v)
}
return list
}
func main() {
// create a list from array of integers
intArr := []int{10, 20, 30, 40, 50, 60}
list1 := CreateLinkedList(intArr)
// create a list from array of strings
strArr := []string{"foo", "bar", "baz", "faz"}
list2 := CreateLinkedList(strArr)
// test inserting at the beginning
list2.AddBeforeHead("hello")
fmt.Println(list1.Display())
fmt.Println(list2.Display())
}
Some official references covering basics of Generics can be found here:
https://go.dev/doc/tutorial/generics
https://go.dev/blog/intro-generics
https://go.dev/tour/generics/1
You can do it either by using interfaces and runtime checks (as you've discovered), or by using code generation. These are the current options you have in Go for generic programming. The Go team is working to add generics to the language - it's a work in progress, and everyone is free to participate in the discussion. Once generics exist, they will provide the solution you seek here.
As for interfaces vs. code generation, there are the performance implications you've mentioned. Code generation will generate tighter code that doesn't need to do runtime checks for most operations; on the other hand, it adds a bit of complexity to the build process of your project. These are the usual tradeoffs of having something resolved at run-time vs. precomputing things at compile-time.

Tricky case with value-to-references in for-range

Look to the code - what do you think the output would be? It's return "Third" instead of "Second" and took me a while to understand why.
Do you know a reason?
I get concept of pass-by-value & pass-by-reference quite well but this case is a bit tricky for people coming from languages like Python. So I decided it worth to share.
package main
import "fmt"
type Record struct {
Id int
Name string
}
var records = []Record{
Record{1, "First"},
Record{2, "Second"},
Record{3, "Third"},
}
func findRecod(id int) (foundRecord *Record) {
for _, record := range records {
if record.Id == id {
foundRecord = &record
// You think we can do a break here but imagine we need to do...
}
// ...something more here
}
return foundRecord
}
func main() {
foundRecord := findRecod(2)
if foundRecord == nil {
fmt.Println("Nothing found")
} else {
fmt.Println("Found: ", foundRecord.Name)
}
}
Run it online to check: https://play.golang.org/p/Y_iAl6m7Ms
I've spent some time figuring out what's going on.
You are returning pointer to a record variable which is reused by each iteration of the loop. Last iteration sets the pointer to the third structure.
The reuse of variable has an enormous advantage. It does not allocate memory in every iteration of the loop. This saves a lot of garbage collection time.
This is well know behaviour described in FAQ.
To fix it, return a pointer to an element of the slice. It is safe as slice elements are referencable in Go.
package main
import "fmt"
type Record struct {
Id int
Name string
}
var records = []Record{
Record{1, "First"},
Record{2, "Second"},
Record{3, "Third"},
}
func findRecod(id int) (foundRecord *Record) {
for i, record := range records {
if record.Id == id {
foundRecord = &records[i]
// You think we can do a break here but imagine we need to do...
}
// ...something more here
}
return foundRecord
}
func main() {
foundRecord := findRecod(2)
if foundRecord == nil {
fmt.Println("Nothing found")
} else {
fmt.Println("Found: ", foundRecord.Name)
}
}
Playground

Generic variadic argument in Go?

I know that Go doesn't support templates or overloaded functions, but I'm wondering if there's any way to do some kind of generic programming for variadic functions anyway?
I have many functions such as these:
func (this Document) GetString(name string, defaults ...string) string {
v, ok := this.GetValueFromDb(name)
if !ok {
if len(defaults) >= 1 {
return defaults[0]
} else {
return ""
}
}
return v.asString
}
func (this Document) GetInt(name string, defaults ...int) int {
v, ok := this.GetValueFromDb(name)
if !ok {
if len(defaults) >= 1 {
return defaults[0]
} else {
return 0
}
}
return v.asInt
}
// etc. for many different types
Is there any way to do this without having so much redundant code?
The most of what you can achieve is usage of interface{} type, something like this:
func (this Document) Get(name string, defaults ...interface{}) interface{} {
v, ok := this.GetValueFromDb(name)
if !ok {
if len(defaults) >= 1 {
return defaults[0]
} else {
return 0
}
}
return v
}
GetValueFromDb function should also be tweaked to return interface{} value and not some wrapper like now.
Then in the client code you can do the following:
value := document.Get("index", 1).(int) // Panics when the value is not int
or
value, ok := document.Get("index", 1).(int) // ok is false if the value is not int
This will yield some runtime overhead though. I'd better stick with separate functions and try to restructure the code somehow.
Here's a working example of how you could change your code.
package main
import (
"fmt"
)
type Document struct{
getSucceeds bool
}
func (d *Document) GetValueFromDb(name string) (interface{}, bool) {
return 1, d.getSucceeds
}
func (this Document) Get(name string, def ...int) interface{} {
v, ok := this.GetValueFromDb(name)
if !ok {
if len(def) >= 1 {
return def[0]
} else {
return 0
}
}
return v
}
func main() {
d1 := Document{true}
d2 := Document{false}
var int1, int2 int
int1 = d1.Get("foo", 2).(int)
int2 = d2.Get("foo", 2).(int)
fmt.Println(int1, int2)
}
Since you know what type you expect for the given name, you can write your Get method in a generic way, returning interface{}, and then assert the type at the call site. See the spec about type assertions.
There are different ways to emulate some aspects of generics in Go. There were lots of discussions on the mailing list. Often, there's a way to restructure code so it's less dependent on generics.
In the client code you can do like this :
res := GetValue("name", 1, 2, 3)
// or
// res := GetValue("name", "one", "two", "three")
if value, ok := res.(int); ok {
// process int return value
} else if value, ok := res.(string); ok {
// process string return value
}
// or
// res.(type) expression only work in switch statement
// and 'res' variable's type have to be interface type
switch value := res.(type) {
case int:
// process int return value
case string:
// process string return value
}

Resources