I want to create linked list code in Go but not sure which style should I use.
*** First Code Start****
package main
import "fmt"
type List struct {
head *Node
}
type Node struct {
next *Node
element int
}
func (list *List) append(element int) {
if list.head == nil {
list.head = &Node{nil, element}
} else {
node := list.head
for node.next != nil {
node = node.next
}
node.next = &Node{nil, element}
}
}
func (list *List) appendFirst(element int) {
list.head = &Node{list.head, element}
}
func (list *List) Print() {
node := list.head
for node != nil {
fmt.Print(node.element, " ")
node = node.next
}
fmt.Println("")
}
func main() {
ll := List{}
for i := 0; i < 10; i++ {
ll.appendFirst(i)
// ll.append(i)
}
ll.Print()
}
*** First Code Stop****
*** Second Code Start****
package main
import "fmt"
type List *Node
type Node struct {
next List
element int
}
func append(list *List, element int) {
if *list == nil {
*list = &Node{nil, element}
} else {
append(&((*list).next), element)
}
}
func appendFirst(list *List, element int) {
*list = &Node{*list, element}
}
func Print(list List) {
node := list
for node != nil {
fmt.Print(node.element, " ")
node = node.next
}
fmt.Println("")
}
func main() {
var list List = nil
for i := 0; i < 10; i++ {
appendFirst(&list, i)
//append(&list, i)
}
Print(list)
}
*** Second Code Stop****
Please let me know which code style should be used.
methods and functions are both valid; a method is just a function with a special receiver argument. Practically it doesn’t make much of a difference. A rule of thumb that some people follow, is to use methods when managing state, as it flows naturally. Note you can also write pointer receivers to modify the value that the receiver is pointing at.
But this answer does not solve my problem. Consider If you are a Go developer how you will write a linked list program. Is there some other much better program.
HOWEVER, keep in mind that whatever you’re doing (both samples) in proper Go is:
func main() {
var list []int
// append
for i := 0; i < 10; i++ {
list = append(list, i)
}
// prepend
for i := 0; i < 10; i++ {
list = append([]int{i}, list...)
}
}
You are right we can use built-in data structures directly and done. But some professor is teaching linked list using go. I had given OOPs based answer and he is not happy with my solution. So I guess, I should go with double pointer based procedural solution.
Naming convention i will fix. But the question is what should be the approach to write code procedural or oops based.
You are right we can use built-in data structures directly and done. But some professor is teaching linked list using go. I had given OOPs based answer and he is not happy with my solution. So I guess, I should go with double pointer based procedural solution.
Are you absolutely sure your lecturer really expecting a LL in Go or something outside the box (it’s quite obvious)?
I had 1 lecturer once secretly expected me to lift a 5+3kg weights with just a bag of raw spaghetti in a structural integrity assignment before while my peers were using other materials like metal wires. The hidden expectation was the business acumen of things like costing and product life-cycle planning (the building only need to have 10 mins lifetime) on top of engineering technicalities.
Site-note:
I’ll give my deepest sigh if your lecturer is really expecting a LL from Go. Treat it like a simulation in life. Sometimes, it throws you lemon. Try make it a lemonade. Good luck. NOTE: the double pointer is totally doable in Go.
Ahhh… Go is not OOP. It does not polymorph or inherit a data type. Method 1 looks like OOP but it’s not.
The methods are duck-typing interfaces. You can’t change any already defined method and you can’t define a new data type to based on an existing definition along with all its methods without rewriting entirely - only composition.
Also, this function in sample 2 is conflicting with the built-in function append. Did you test your program before submitting it to your lecturer? Go developer can easily detect just by reading the code directly.
It is great that you are coding this data structure, and welcome to the Go forum.
Use the first approach, your first implementation. I think the second implementation is not the usual way to code in Go, I do not like the if *list == nil, as it has too many pointers and they make the code harder to read/write.
Now, when writing a data structure of any kind, you should also have a lot of unit tests. Also try to use generics (your list should be able to store any data type not just int).
Also make the append method public (Append), and add comments on top of the append method and the Node datastructure.
Oh yeah… I nearly forgotten: try provide a complete Create, Read, Update, and Delete (CRUD) when developing an “unsafe” library. By right, the hardest part of LL is usually Delete because in C language, memory are managed manually. Since you’re in Go, the garbage collector will obviously back you up so you will have to consult your lecturer’s expecations whether the manual efforts are required in your demo.
You already done:
Append - add an element into the list to the last position Prepend - add an element into the list to the first position String - printout the list as string
Missing APIs are:
Len / Length - provide the total length of the list Index - read value by position Insert - add an element by position Pop - remove an element by position Search - scan index by value Scan - scan all indices by value Join - join 2 linked list into 1 Split - split 1 list into 2 different linked list Copy - duplicate a list Delete / Destroy - remove all elements by freeing the memory spaces and then the list Sanitize - deep check each element is usable and safe. Zero - set all element’s values to zero (usually security released where confidential data are zeroed out after use, before free). Reserve - reserve and initialise a set of elements in the list before use (used in time-sensitive environment like audio/video).
That’s all I believe. Please check with your deciding person. Good luck.
This is a great idea @hollowaykeanho. You should also have an interface with these methods, and your data structure implements it. When people look at your code, they will see the interface and have a clear idea of what functionality you offer.
Thank you for your answer, I think that you are onto something. What do you mean by “Single purpose package favors functions pattern” ?
What is this functions pattern ? Indeed the strings package exposes some functions (not an object implementing an interface), but a data structure is an object offering functionality. Please give more details.