This is a creation in Article, where the information may have evolved or changed.
This article implements a custom stack to learn the custom types and methods of the Go language
First of all, the concept of the stack is not much to say, it is a support to insert or delete from the top of the linear table, nonsense less say on the code.
GOPATH
under new stack directory, all implementations of the stack are in the stack.go
file.
First, you need a structure that can hold the data.
type Stack []interfice {}
This declares that the stack is a slice of the empty interface type (the slices in the go language can be understood as a variable-length array). Because the go language implements an empty interface for all types, any type of value can be stored in a stack.
Next, because the underlying data type of the stack is a slice, we can do it for its implementations Len()
and Cap()
methods to get its length and capacity (the way in which the first capitalization of the go language is outside of the package, similar to the public method for classes in Java or C + +).
func (stack Stack) Len() int { return len(stack)}
The definition of the method is as above. The func
keyword is used to define the method, followed by the type of the method, which is Len()
used for Stack
this type of value, which is often referred to as the "receiver" of the method (the Go language type declaration, the variable declaration is placed after the name of the type) And then the method name and the parameter list, where the argument is null, and the last is the return value of the method, which is int
. The implementation of the method invokes the built-in function of the go language len()
, len()
returning the length of the slice and the array.
Cap()
Method and Len()
similar, its implementation also calls the built-in function cap()
to get the length of the slice
func (stack Stack) Cap() int { return cap(stack)}
Next, implement its key approach Push()
, Top()
andPop()
func (stack *Stack) Push(value interface{}) { *stack = append(*stack, value)}
Push()
the receiver of the method is a stack-type pointer (the go pointer is written in a C + + style, preceded by an * sign). All method parameters of the go language are value passing, and the receiver is actually passed into the method as a parameter of the method. If you pass all the slices or the array into the method, actually copy the value of the slice or array into the method, at this point, the operation of the slice or array in the method does not affect the original value outside the method. If you want the action in the method to affect the original value outside the method, you should use the pointer as a parameter, and the manipulation of the pointer will react directly to the original value in memory. Here we want to change the original value ( stack
adding data to the original), so the receiver is a pointer. The parameter of a method is a value of a interface{}
type, which means that the method can accept any type as a parameter. The implementation of the method uses the built append()
-in function to add new values to the end of the slice.
func (stack Stack) Top() (interface{}, error) { if len(stack) == 0 { return nil, errors.New("Out of index, len is 0") } return stack[len(stack) - 1], nil}
Top()
method returns a value of any type and one error
(yes, the Go language method can return multiple values). When the stack is empty, it returns a null value and a value of a type, which is error
errors
created using the package's New()
function. Returns the last value of the underlying slice and an empty one when the stack is not empty error
.
func (stack *Stack) Pop() (interface{}, error) { theStack := *stack if len(theStack) == 0 { return nil, errors.New("Out of index, len is 0") } value := theStack[len(theStack) - 1] *stack = theStack[:len(theStack) - 1] return value, nil}
Pop()
The receiver of the method is also a stack pointer. One theStack[:len(theStack) - 1]
way to do this is to take a sub-slice in go, with :
both the start index and the end index. You can omit the starting index at 0. The end index can also be omitted, and the value of the slice is ended when omitted len()
.
There is also an easy IsEmpty()
way to
func (stack Stack) IsEmpty() bool { return len(stack) == 0}
All of the above methods are completed, write one stack_test.go
to test stack.go
, run go test in the package directory to see the results. The test can be installed into the stack package by using the Go Install command GOPATH
, and it will be possible to refer to it yourself in other projects Stack
.
Complete source is short, directly posted here
Stack.go
package stackimport "errors"type Stack []interface {}func (stack Stack) Len() int { return len(stack)}func (stack Stack) IsEmpty() bool { return len(stack) == 0}func (stack Stack) Cap() int { return cap(stack)}func (stack *Stack) Push(value interface{}) { *stack = append(*stack, value)}func (stack Stack) Top() (interface{}, error) { if len(stack) == 0 { return nil, errors.New("Out of index, len is 0") } return stack[len(stack) - 1], nil}func (stack *Stack) Pop() (interface{}, error) { theStack := *stack if len(theStack) == 0 { return nil, errors.New("Out of index, len is 0") } value := theStack[len(theStack) - 1] *stack = theStack[:len(theStack) - 1] return value, nil}
Stack_test.go
Package Stackimport ("testing") Func Teststack_len (t *testing. T) {var mystack Stack Mystack.push (1) mystack.push ("test") if mystack.len () = = 2 {t.Log ("Pass STACK.L En ")} else {t.error (" Failed stack.len ")}}func teststack_isempty (t *testing. T) {var mstack Stack if Mstack.isempty () {T.Log ("Pass stack.isempty")} else {t.error ("Failed St Ack. IsEmpty ")}}func Teststack_cap (t *testing. T) {mystack: = Make (Stack, 3) if mystack.cap () = = 3 {t.Log ("Pass stack.cap")} else {t.error ("Fa iled stack.cap ")}}func Teststack_push (t *testing. T) {var mstack Stack Mstack.push (3) if mstack.len () = = 1 {t.Log ("Pass Stack.push")} else {T. Error ("Failed stack.push")}}func teststack_top (t *testing. T) {var Mstack Stack If _, Err: = Mstack.top (); err = = Nil {t.error ("Failed stack.top")} Mstack.push (3) If value, _: = Mstack.top (); Value = = 3 {t.Log ("Pass StAck. Top ")} else {T.errorf (" Failed stack.top, value is%d ", value)}}func Teststack_pop (t *testing. T) {var Mstack Stack If _, Err: = Mstack.pop (); err = = Nil {t.error ("Failed stack.top")} Mstack.push ("Test") Mstack.push (3) if value, _: = Mstack.pop (); Value = = 3 && mstack.len () = = 1 {t.Log ("Pass Stack.pop")} else {T.errorf ("Failed Stack.pop, VA Lue is%d, Len is%d ", Value, Mstack.len ())}}
Note
- All documentation of the go language's built-in methods can be found in the go source
src/builtin/buildin.go