How to get data from a []string descendent

Hello, I have a struct defined as follows:

type Stack []string

func (s Stack) Empty() bool {
	return len(s) == 0
}

func (s Stack) Peek() string {
	return s[len(s) - 1]
}

func (s *Stack) Push(ss string) {
	*s = append(*s, ss)
}

func (s *Stack) Pop() string {
	ss := (*s)[len(*s) - 1]
	*s = (*s)[:len(*s) - 1]
	return ss
}

func (s Stack) Size() int {
	return len(s)
}

Having finished with such a Stack type, I would like to transfer its contents to a standard slice of string, but I cannot figure out how. Even though my Stack class descends (is one allowed to say that with Go??!!) from a string slice, it doesn’t appear to be assignable to or from a string slice. I just want a neat, short, idiomatic way of copying from my Stack type to a []string. Can anyone help, thanks.

1 Like

try this:

package main

import "fmt"

type Stack []string

func main() {
    var s Stack
    s = append(s, "this", "is")
    fmt.Printf("%T, %v\n", []string(s), []string(s))
}

Thanks, Charles with your help, I got it working. I was declaring the Stack variable as s := New(stacks.Stack) which was returning a pointer to a Stack. Changing the declaration to var s stack.Stack did the trick. Though, I’m wondering if, armed with my newly acquired pointer awareness, I should convert it to an all pointer implementation. Maybe best to get the whole thing working before making wholesale changes.

Convention is to be consistent and that receivers are all pointers or values.

Hence my unease. I plumped for an all pointer implementation and it it all seems to work…

package stacks

type Stack []string

func (s *Stack) Empty() bool {
	return len(*s) == 0
}

func (s *Stack) Peek() string {
	return (*s)[len(*s) - 1]
}

func (s *Stack) Push(ss string) {
	*s = append(*s, ss)
}

func (s *Stack) Pop() string {
	ss := (*s)[len(*s) - 1]
	*s = (*s)[:len(*s) - 1]
	return ss
}

func (s *Stack) Size() int {
	return len(*s)
}
package stacks

import (
	"fmt"
	"testing"
)

func TestStack(t *testing.T) {
	var test Stack
	test.Push("1")
	test.Push("2")
	if test.Peek() != "2" {
		t.Error("test.Peek() expected 2, got ", test.Peek())
	}
	if test.Size() != 2 {
		t.Error("test.Size() expected 2, got ", test.Size())
	}
	test.Pop()
	if test.Peek() != "1" {
		t.Error("test.Pop() expected 1, got ", test.Peek())
	}
	if test.Empty() {
		t.Error("test.Empty() expected false, got ", test.Empty())
	}
	fmt.Println([]string(test))
}

You didn’t really have an options, since your Pop and Push need to manipulate the actual slice. PS - you should be checking in several methods that len(*s) - 1 >= 0 or you could panic due to an out-of-bounds index.

You can really just use a struct wrapping your []string, something like:

type Stack struct {
	s []string
}

func (s *Stack) Empty() bool {
	return len(s.s) == 0
}

func (s *Stack) Peek() string {
	return s.s[len(s.s)-1]
}

func (s *Stack) Push(ss ...string) {
	s.s = append(s.s, ss...)
}

func (s *Stack) Pop() string {
	ss := s.s[len(s.s)-1]
	s.s = s.s[:len(s.s)-1]
	return ss
}

func (s *Stack) Size() int {
	return len(s.s)
}
1 Like

Interesting. I’ll have to study this and play with it. I’m grateful for everyone’s help - I’ve got 20+ years of Delphi OOP experience to unlearn so some of my solutions will not necessarily be optimum Golang!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.