func (comp *Intcode) Step(input int) {
	for comp.IsRunning {
		opcode, paramIndexes := comp.GetOpCodeAndParamIndexes()
		param1, param2, param3 := paramIndexes[0], paramIndexes[1], paramIndexes[2]
		switch opcode {
		case 1, 2, 7, 8:
			comp.ResizeMemory(param1, param2, param3)
		case 5, 6:
			comp.ResizeMemory(param1, param2)
		case 3, 4, 9:
			comp.ResizeMemory(param1)
		}
		switch opcode {
		case 99:  
			comp.IsRunning = false
		case 1:  
			comp.PuzzleInput[param3] = comp.PuzzleInput[param1] + comp.PuzzleInput[param2]
			comp.InstructionIndex += 4
		case 2:  
			comp.PuzzleInput[param3] = comp.PuzzleInput[param1] * comp.PuzzleInput[param2]
			comp.InstructionIndex += 4
		case 3:  
			if input == -2 {
				return
			}
			comp.PuzzleInput[param1] = input
			comp.InstructionIndex += 2
			input = -2
		case 4:  
			output := comp.PuzzleInput[param1]
			comp.Outputs = append(comp.Outputs, output)
			comp.InstructionIndex += 2
		case 5:
			if comp.PuzzleInput[param1] != 0 {
				comp.InstructionIndex = comp.PuzzleInput[param2]
			} else {
				comp.InstructionIndex += 3
			}
		case 6:
			if comp.PuzzleInput[param1] == 0 {
				comp.InstructionIndex = comp.PuzzleInput[param2]
			} else {
				comp.InstructionIndex += 3
			}
		case 7:
			if comp.PuzzleInput[param1] < comp.PuzzleInput[param2] {
				comp.PuzzleInput[param3] = 1
			} else {
				comp.PuzzleInput[param3] = 0
			}
			comp.InstructionIndex += 4
		case 8:
			if comp.PuzzleInput[param1] == comp.PuzzleInput[param2] {
				comp.PuzzleInput[param3] = 1
			} else {
				comp.PuzzleInput[param3] = 0
			}
			comp.InstructionIndex += 4
		case 9:
			comp.RelativeBase += comp.PuzzleInput[param1]
			comp.InstructionIndex += 2
		default:
			log.Fatalf("Error: unknown opcode %v at index %v", opcode, comp.PuzzleInput[comp.InstructionIndex])
		}
	}
}
Step will read the next 4 values in the input `sli` and make updates
according to the opcodes
Update to run iteratively (while the computer is running)
it will also return out if a -1 input is asked for
then call Step again to provide the next input, or run with -1 from the start
to run the computer until it asks for an input OR terminates
package main
import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
	inputFile := util.ReadFile("../input.txt")
	splitStrings := strings.Split(inputFile, ",")
	inputNumbers := make([]int, len(splitStrings))
	for i, v := range splitStrings {
		inputNumbers[i], _ = strconv.Atoi(v)
	}
	network := Network{}
	network.Init(inputNumbers)
	natPacket := [2]int{}
	var lastNatY int
	for {
		allNatsWaiting := true
		for i := 0; i < 50; i++ {
			if len(network.queues[i]) == 0 {
				network.computers[i].Step(-1)
			} else {
				allNatsWaiting = false
				front := network.queues[i][0]
				network.computers[i].Step(front[0])
				network.computers[i].Step(front[1])
				network.queues[i] = network.queues[i][1:]
			}
			for len(network.computers[i].Outputs) > 2 {
				destination := network.computers[i].Outputs[0]
				packet := [2]int{network.computers[i].Outputs[1],
					network.computers[i].Outputs[2]}
				network.computers[i].Outputs = network.computers[i].Outputs[3:]
				if destination == 255 {
					natPacket = packet
				} else {
					network.queues[destination] = append(network.queues[destination], packet)
				}
			}
		}
		if allNatsWaiting {
			if lastNatY == natPacket[1] {
				fmt.Println(lastNatY, "written to NAT twice")
				return
			}
			network.queues[0] = append(network.queues[0], natPacket)
			lastNatY = natPacket[1]
		}
	}
}
type Network struct {
	computers []*Intcode
	queues    [][][2]int  
}
func (network *Network) Init(puzzleInput []int) {
	network.computers, network.queues = make([]*Intcode, 50), make([][][2]int, 50)
	for i := 0; i < 50; i++ {
		network.computers[i] = MakeComputer(puzzleInput)
		network.computers[i].Step(i)
	}
}
type Intcode struct {
	PuzzleInput      []int  
	InstructionIndex int    
	RelativeBase     int    
	Outputs          []int  
	IsRunning        bool   
}
func MakeComputer(PuzzleInput []int) *Intcode {
	puzzleInputCopy := make([]int, len(PuzzleInput))
	copy(puzzleInputCopy, PuzzleInput)
	comp := Intcode{
		puzzleInputCopy,
		0,
		0,
		make([]int, 0),
		true,
	}
	return &comp
}