gotables

package module
v0.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2020 License: MIT Imports: 25 Imported by: 2

README

Build Status

See gotables godoc

Gotables & FlatBuffers

The focus of recent work is on support for Google FlatBuffers. If you don't want to get into the weeds of the FlatBuffers API, gotables will save you a lot of time. But a warning up front: this implementation doesn't support complex data structures such as Monsters. Only rectangular tables.

To distinguish the gotables FlatBuffers support from something that would support Monsters, I have called it FlatTables.

In a nutshell, gotables.FlatTables does the following:

  • Makes it very easy to create a FlatBuffers schema and associated table-type-specific Go code to access FlatBuffers data.

  • Makes it a piece of cake (rectangular cake) to populate a set of one or more FlatBuffers tables as a []byte array.

  • Gives you easy methods (generated specifically for your table data types) to read from a FlatBuffers []byte array.

  • Provides a worked example (in the form of a main program) specific to your schema that is a tutorial you can use directly in your code.

  • This particular tutorial is the flattables_sample_main.go generated for the flattables_sample package I created from my gotables file of tables. Your own generated code will produce a tutorial main program specific to your own gotables file of tables. Can you believe it?

  • See https://github.com/urban-wombat/flattables for instructions on how to install FlatTables and run the flattables_sample package, or create and run your own.

  • https://urban-wombat.github.io has an introduction to gotables.

gotables

gotables reinvents the wheel as a table. Go (golang) Table data format is simple and self-describing. Often data and configurations can be expressed best as tables, or can be flattened or normalised into tables. And events which are simple structs (or records) can be batched into tables for transmission.

`go get -u github.com/urban-wombat/gotables`

Here's the gotables API ...

gotables API - a rich set of helper functions and methods

Here are the Release Notes ...

https://github.com/urban-wombat/gotables/releases

## Command line utilities ...
CLI Purpose
gotecho echo 1 or all tables from a gotables file
gotsyntax check syntax of 1 or more gotables files
flattablesc generate Google FlatBuffers code

Contact:

Why Use gotables?

  1. Often enough the data you want to represent is intrinsically tabular, or should be.

  2. You want tables of data to be more readable by human beings. Be able to look at the data and spot any problems.

  3. You want to eliminate repetitive metadata such as tags, and reduce the size of each tabular chunk of data. Data name and type are mentioned only once in a gotables Table.

  4. Sometimes the data you want to represent is intrinsically tabular, and really you don't want any elements to be missing. And if they are, you want it to be obvious.

  5. It feels like overkill to set up a relational database table (or tables) to store (and modify) your software configurations, or to use a database as a conduit for sharing messages or data flows between processes or goroutines.

  6. If you are sending messages between goroutines in Go, you can use a gotables Table or a set of Tables (a TableSet) to send data through your channels. A Table can be sent and received as an object or as a string.

  7. gotables has methods and functions to perform tasks in these broad categories:

    1. Instantiate a gotables.Table or gotables.TableSet from a file, a string, a Go binary object, or a segment of an existing table.

    2. Get and Set values. Most Go types are supported.

    3. Sort and Search a table. Multiple keys and reverse sort and search are supported.

    4. Merge two tables (with shared key(s)) into one. NaN and zero values are handled consistently.

    5. SortUnique to remove NaN and zero values.

  8. gotables Table is simple. For instance, sorting (and searching) a table is probably as easy as it can possibly be. And that can mean multiple sort/search keys, and even reverse keys. It's very simple. And if a wrong column name is used, or you forget to set sort keys before sorting, the gotables error handling system will notice and return to you a meaningful error message.

  9. Some advantages are subtle. For instance, versioning is easier. Your program can test for the presence of particular columns (and their types) before accessing potentially new columns of data. And sending a table with additional columns will not break downstream code.

  10. gotables is written in the Go language, using purely Go libraries. No third-party libraries will be used. If down the track non-Go libraries are needed, a separate distribution will be created (to contain any third-party dependency issues) and will itself use gotables as a third-party library to maintain separation. The core gotables library will *not use third-party libraries.

Go Doc for gotables

https://urban-wombat.github.io

What is a gotables.Table?

A gotables.Table is a table of data with the following sections:

  1. A table name in square brackets: [planets]
  2. A row of one or more column names: name mass
  3. A row of one or more column types: string float64
  4. Zero or more rows of data: "Mercury" 0.055
  5. One or more blank lines before any subsequent table(s)

It's a bit like a slice of struct.

Here's an example:

[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Mercury"   0.055      0.4     0     0 "my"
"Venus"     0.815      0.7     0     1 "very"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Jupiter" 318.0        5.2    79     4 "just"
"Saturn"   95.0        9.5    62     5 "sat"
"Uranus"   15.0       19.2    27     6 "upon"
"Neptune"  17.0       30.6    13     7 "nine"
"Pluto"     0.002     39.4     5     8 "porcupines"

Most of the Go builtin data types can be used (except complex64 and complex128).

Here is a simple program that parses the table into a gotables.Table and echoes it back out:

// main_echo.go

package main

import (
    "github.com/urban-wombat/gotables"
    "fmt"
    "log"
)

func main() {
    tableString :=
    `[planets]
    name         mass distance moons index mnemonic
    string    float64  float64   int   int string
    "Mercury"   0.055      0.4     0     0 "my"
    "Venus"     0.815      0.7     0     1 "very"
    "Earth"     1.0        1.0     1     2 "elegant"
    "Mars"      0.107      1.5     2     3 "mother"
    "Jupiter" 318.0        5.2    79     4 "just"
    "Saturn"   95.0        9.5    62     5 "sat"
    "Uranus"   15.0       19.2    27     6 "upon"
    "Neptune"  17.0       30.6    13     7 "nine"
    "Pluto"     0.002     39.4     5     8 "porcupines"
    `
    
    table, err := gotables.NewTableFromString(tableString)
    if err != nil {
        log.Println(err)
    }
    
    fmt.Println("Default String() padded output\n")
    fmt.Println(table)

    // Notice that the columns of data are padded with spaces, and numeric types are right-aligned.
    // This reflects the opinion that human readability is important.

    fmt.Println("For unpadded output use StringUnpadded()\n")
    fmt.Println(table.StringUnpadded())
}

Here's the output:

Default String() padded output

[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Mercury"   0.055      0.4     0     0 "my"
"Venus"     0.815      0.7     0     1 "very"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Jupiter" 318.0        5.2    79     4 "just"
"Saturn"   95.0        9.5    62     5 "sat"
"Uranus"   15.0       19.2    27     6 "upon"
"Neptune"  17.0       30.6    13     7 "nine"
"Pluto"     0.002     39.4     5     8 "porcupines"

For unpadded output use StringUnpadded()

[planets]
name mass distance moons index mnemonic
string float64 float64 int int string
"Mercury" 0.055 0.4 0 0 "my"
"Venus" 0.815 0.7 0 1 "very"
"Earth" 1 1 1 2 "elegant"
"Mars" 0.107 1.5 2 3 "mother"
"Jupiter" 318 5.2 79 4 "just"
"Saturn" 95 9.5 62 5 "sat"
"Uranus" 15 19.2 27 6 "upon"
"Neptune" 17 30.6 13 7 "nine"
"Pluto" 0.002 39.4 5 8 "porcupines"

Can you show me some worked examples?

For these examples to compile and run for you, you need to go get and import "github.com/urban-wombat/gotables" and prefix function and method calls with gotables.

// example1.go

package main

import (
    "fmt"
    "log"
    "github.com/urban-wombat/gotables"
)

// Copyright (c) 2017 Malcolm Gorman

func main() {
    tableString :=
    `[planets]
    name         mass distance moons index mnemonic
    string    float64  float64   int   int string
    "Mercury"   0.055      0.4     0     0 "my"
    "Venus"     0.815      0.7     0     1 "very"
    "Earth"     1.0        1.0     1     2 "elegant"
    "Mars"      0.107      1.5     2     3 "mother"
    "Jupiter" 318.0        5.2    79     4 "just"
    "Saturn"   95.0        9.5    62     5 "sat"
    "Uranus"   15.0       19.2    27     6 "upon"
    "Neptune"  17.0       30.6    13     7 "nine"
    "Pluto"     0.002     39.4     5     8 "porcupines"
    `

    var err error

    table, err := gotables.NewTableFromString(tableString)
    if err != nil {
    	log.Println(err)
    }
    fmt.Println("Table [planets] already in distance order.")
    fmt.Println("Distance is in AU: Earth units from the Sun")
    fmt.Println(table)

    var rowIndex int

    fmt.Println("Get the name and mass of the first planet.")
    rowIndex = 0
    fmt.Printf("rowIndex = %d\n", rowIndex)
    name, err := table.GetString("name", rowIndex)
    if err != nil {
    	log.Println(err)
    }
    fmt.Printf("name = %s\n", name)

    mass, err := table.GetFloat64("mass", rowIndex)
    if err != nil {
    	log.Println(err)
    }
    fmt.Printf("mass = %f\n", mass)
    fmt.Println()

    fmt.Println("Get and Set the mnemonic of the second planet: index 1")
    rowIndex = 1
    fmt.Printf("rowIndex = %d\n", rowIndex)
    name, err = table.GetString("name", rowIndex)
    if err != nil {
    	log.Println(err)
    }
    fmt.Printf("name = %s\n", name)

    mnemonic, err := table.GetString("mnemonic", rowIndex)
    if err != nil {
    	log.Println(err)
    }
    fmt.Printf("mnemonic = %q\n", mnemonic)

    err = table.SetString("mnemonic", rowIndex, "*VERY*")
    if err != nil {
    	log.Println(err)
    }

    mnemonic, err = table.GetString("mnemonic", rowIndex)
    if err != nil {
    	log.Println(err)
    }
    fmt.Printf("mnemonic = %q\n", mnemonic)
    fmt.Println()

    fmt.Println("Sort and Search.")
    sortKey := "name"
    fmt.Printf("sortKey = %q\n", sortKey)
    err = table.SetSortKeys(sortKey)
    if err != nil {
    	log.Println(err)
    }
    err = table.Sort()
    if err != nil {
    	log.Println(err)
    }

    planet := "Saturn"
    fmt.Printf("search value: planet = %q\n", planet)
    rowIndex, err = table.Search(planet)
    if err != nil {
    	log.Println(err)
    }

    moons, err := table.GetInt("moons", rowIndex)
    if err != nil {
    	log.Println(err)
    }

    fmt.Println(table)
    fmt.Printf("%s has %d moons.\n", planet, moons)
    fmt.Println()

    fmt.Println("Sort and Search Range.")
    err = table.SetSortKeys("moons")
    if err != nil {
    	log.Println(err)
    }

    err = table.Sort()
    if err != nil {
    	log.Println(err)
    }

    moons = 2
    firstRowIndex, lastRowIndex, err := table.SearchRange(moons)
    if err != nil {
    	log.Println(err)
    }
    var planets int
    if err == nil {
    	fmt.Println("Found at least 1 row with 2 moons.")
    	planets = lastRowIndex - firstRowIndex + 1
    } else {
    	// moons = 3: [planets].Search([3]) search values not in table: [3]
    	fmt.Println(err)
    	planets = 0
    }
    fmt.Println(table)
    fmt.Printf("%d planets have %d moons.\n", planets, moons)
    fmt.Println()


    // Sort Unique.

    tableString =
    `[Unique]
    key n       s
    int float32 string
    2   0       "two point two"
    2   2.2     ""
    1   1.1     "one point one"
    3   3.3     "three point three"
    3   3.3     ""
    3   NaN     "three point three"
    4   0.0     "neither zero nor same XX"
    4   NaN     "neither zero nor same YY"
    4   4.4     "neither zero nor same ZZ"
    4   NaN     "neither zero nor same AA"
    5   NaN     "minus 5"
    5   -0      "minus 5"
    5   -5      "minus 5"
    `
    table, err = gotables.NewTableFromString(tableString)
    if err != nil {
    	log.Println(err)
    }

    fmt.Println("Table [Unique] in no particular order, contains duplicate key values and zero and NaN values.")
    fmt.Println(table)

    sortKey = "key"
    fmt.Printf("sortKey = %q\n", sortKey)
    err = table.SetSortKeys(sortKey)
    if err != nil {
    	log.Println(err)
    }

    tableUnique, err := table.SortUnique()
    if err != nil {
    	log.Println(err)
    }
    fmt.Printf("table [%s] sorted unique by key %q\n", tableUnique.Name(), sortKey)
    fmt.Println(tableUnique)
}

Output:

Table [planets] already in distance order.
Distance is in AU: Earth units from the Sun
[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Mercury"   0.055      0.4     0     0 "my"
"Venus"     0.815      0.7     0     1 "very"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Jupiter" 318.0        5.2    79     4 "just"
"Saturn"   95.0        9.5    62     5 "sat"
"Uranus"   15.0       19.2    27     6 "upon"
"Neptune"  17.0       30.6    13     7 "nine"
"Pluto"     0.002     39.4     5     8 "porcupines"

Get the name and mass of the first planet.
rowIndex = 0
name = Mercury
mass = 0.055000

Get and Set the mnemonic of the second planet: index 1
rowIndex = 1
name = Venus
mnemonic = "very"
mnemonic = "*VERY*"

Sort and Search.
sortKey = "name"
search value: planet = "Saturn"
[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Earth"     1.0        1.0     1     2 "elegant"
"Jupiter" 318.0        5.2    79     4 "just"
"Mars"      0.107      1.5     2     3 "mother"
"Mercury"   0.055      0.4     0     0 "my"
"Neptune"  17.0       30.6    13     7 "nine"
"Pluto"     0.002     39.4     5     8 "porcupines"
"Saturn"   95.0        9.5    62     5 "sat"
"Uranus"   15.0       19.2    27     6 "upon"
"Venus"     0.815      0.7     0     1 "*VERY*"

Saturn has 62 moons.

Sort and Search Range.
Found at least 1 row with 2 moons.
[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Venus"     0.815      0.7     0     1 "*VERY*"
"Mercury"   0.055      0.4     0     0 "my"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Pluto"     0.002     39.4     5     8 "porcupines"
"Neptune"  17.0       30.6    13     7 "nine"
"Uranus"   15.0       19.2    27     6 "upon"
"Saturn"   95.0        9.5    62     5 "sat"
"Jupiter" 318.0        5.2    79     4 "just"

1 planets have 2 moons.

Table [Unique] in no particular order, contains duplicate key values and zero and NaN values.
[Unique]
key       n s
int float32 string
  2     0.0 "two point two"
  2     2.2 ""
  1     1.1 "one point one"
  3     3.3 "three point three"
  3     3.3 ""
  3     NaN "three point three"
  4     0.0 "neither zero nor same XX"
  4     NaN "neither zero nor same YY"
  4     4.4 "neither zero nor same ZZ"
  4     NaN "neither zero nor same AA"
  5     NaN "minus 5"
  5    -0.0 "minus 5"
  5    -5.0 "minus 5"

sortKey = "key"
table [Unique] sorted unique by key "key"
[Unique]
key       n s
int float32 string
  1     1.1 "one point one"
  2     2.2 "two point two"
  3     3.3 "three point three"
  4     4.4 "neither zero nor same AA"
  5    -5.0 "minus 5"

Documentation

Index

Examples

Constants

View Source
const (
	ByteSlice     = "[]byte"
	Uint8Slice    = "[]uint8"
	Bool          = "bool"
	Byte          = "byte"
	Float32       = "float32"
	Float64       = "float64"
	Int           = "int"
	Int16         = "int16"
	Int32         = "int32"
	Int64         = "int64"
	Int8          = "int8"
	Rune          = "rune"
	String        = "string"
	Uint          = "uint"
	Uint16        = "uint16"
	Uint32        = "uint32"
	Uint64        = "uint64"
	Uint8         = "uint8"
	GotablesTable = "*Table"
	TimeTime      = "time.Time"
)

The 19 gotables column type constants.

View Source
const (
	FlagRequired = true
	FlagOptional = false
)

Utility function to test string flags.

It avoids boilerplate code testing flags.

It can be called and:-

(1) Required flags can trust the existence of an argument.

// Required flag.
exists, err := UtilCheckStringFlag("r", flags.r, UtilFlagRequired)
if !exists {
	fmt.Fprintf(os.Stderr, "%v\n", err)
	os.Exit(1)
}

(2) Optional flags can test exists.

// Optional flag.
exists, err := UtilCheckStringFlag("o", flags.o, UtilFlagOptional)
if exists {
	// Do something with flag.
}

Variables

View Source
var MaxTime time.Time = time.Unix(1<<63-62135596801, 999999999) // 292277024627-12-07T02:30:07.999999999+11:00

This MaxTime value is correct as far as I know (the alternative posited time.Unix(1<<63-1, 0) is time.Before()).

View Source
var MinTime time.Time = time.Time{} // 0001-01-01T00:00:00Z

Functions

func IsNumericColType

func IsNumericColType(colType string) (bool, error)

Returns true for those Go types that are numeric.

Go types NOT supported: complex64 complex128

func IsSliceColType

func IsSliceColType(colType string) (bool, error)

func IsTableColType

func IsTableColType(colType string) (bool, error)

func IsValidColName

func IsValidColName(colName string) (bool, error)

Note: The same validity rules apply to both table names and col names.

func IsValidColType

func IsValidColType(colType string) (bool, error)

Returns true for those Go types that Table supports.

gotables.Table supports:-
* Go types - except complex64 complex128
* []byte and []uint8

func IsValidTableName

func IsValidTableName(tableName string) (bool, error)

Note: The same validity rules apply to both table names and col names. This tests table name WITHOUT surrounding square brackets. Text part only.

func SearchFirst

func SearchFirst(n int, f func(int) bool) int

gotables.SearchFirst() calls the Go library function sort.Search() which has search-first behavior.

Comparison of sort.Search() and gotables.SearchLast() describing their mirrored relationship.

Assume data is a zero-based array/slice of elements sorted in ascending order. Each search function returns an index into data.

----------------------------------------- | -----------------------------------------------
Go library sort.Search()                  | gotables.SearchLast()
----------------------------------------- | -----------------------------------------------
Index of >= search term.                  | Index of <= search term.
Finds index of FIRST instance equal.      | Finds index of LAST instance equal.
Multiples will be at and AFTER index.     | Multiples will be at and BEFORE index.
if term is missing from data,             | If term is missing from data,
  where it WOULD be                       |   where it WOULD be
  is insert BEFORE index.                 |   is insert AFTER index.
Missing at high end of data returns:      | Missing at low end of data returns:
  index 1-greater than last element,      |   index 1-less than first element, -1,
    len(data),                            |   which means it would insert AFTER -1 data,
  which means it would insert BEFORE      |   which would be an insert to
    len(data),                            |   before start of data array.
  which would be an append to data array. |
  Check index to avoid bounds errors.     |   Check index != -1 to avoid bounds errors.
Example: multiple search terms present    | Example: multiple search terms present
  data: [4 8 10 10 10 20 23 29]           |   data: [4 8 10 10 10 20 23 29]
  index: 0 1  2  3  4  5  6  7            |   index: 0 1  2  3  4  5  6  7
  x: 10                                   |   x: 10
  sort.Search(x, func) = 2 (finds FIRST)  |   gotables.SearchLast(x, func) = 4 (finds LAST)
----------------------------------------- | -----------------------------------------------

This binary search has two steps: (1) binary search for x, and (2) check if x was found.

Strange, huh? Go library sort.Search() works the same way, except in the
  opposite (mirror image) direction.
See https://golang.org/pkg/sort/#Search

(1) Binary search for x.
x := 23
i := gotables.SearchFirst(len(data), func(i int) bool { return data[i] >= x })

(2) Check that x was found.
if i < len(data) && data[i] == x {
	// x is present at data[i]
} else {
	// x is not present in data,
	// but i is the index where it would be inserted.
	// Note that i can be len(data) which does not exist in data.
}

func SearchLast

func SearchLast(n int, f func(int) bool) int

gotables.SearchLast() mirrors the Go library function sort.Search()

Comparison of sort.Search() and gotables.SearchLast() describing their mirrored relationship.

Assume data is a zero-based array/slice of elements sorted in ascending order. Each search function returns an index into data.

----------------------------------------- | -----------------------------------------------
Go library sort.Search()                  | gotables.SearchLast()
----------------------------------------- | -----------------------------------------------
Index of >= search term.                  | Index of <= search term.
Finds index of FIRST instance equal.      | Finds index of LAST instance equal.
Multiples will be at and AFTER index.     | Multiples will be at and BEFORE index.
if term is missing from data,             | If term is missing from data,
  where it WOULD be                       |   where it WOULD be
  is insert BEFORE index.                 |   is insert AFTER index.
Missing at high end of data returns:      | Missing at low end of data returns:
  index 1-greater than last element,      |   index 1-less than first element, -1,
    len(data),                            |   which means it would insert AFTER -1 data,
  which means it would insert BEFORE      |   which would be an insert to
    len(data),                            |   before start of data array.
  which would be an append to data array. |
  Check index to avoid bounds errors.     |   Check index != -1 to avoid bounds errors.
Example: multiple search terms present    | Example: multiple search terms present
  data: [4 8 10 10 10 20 23 29]           |   data: [4 8 10 10 10 20 23 29]
  index: 0 1  2  3  4  5  6  7            |   index: 0 1  2  3  4  5  6  7
  x: 10                                   |   x: 10
  sort.Search(x, func) = 2 (finds FIRST)  |   gotables.SearchLast(x, func) = 4 (finds LAST)
----------------------------------------- | -----------------------------------------------

This binary search has two steps: (1) binary search for x, and (2) check if x was found.

Strange, huh? Go library sort.Search() works the same way, except in the
  opposite (mirror image) direction.
See https://golang.org/pkg/sort/#Search

(1) Binary search for x.
x := 23
i := gotables.SearchLast(len(data), func(i int) bool { return data[i] <= x })

(2) Check that x was found.
if i >= 0 && data[i] == x {
	// x is present at data[i]
} else {
	// x is not present in data,
	// but i is the index where it would be inserted.
	// Note that i can be -1 which does not exist in data.
}

func TypesList

func TypesList() string

Return a slice of string with each of the types supported by gotables.

Conspicuously absent are the complex types (complex64 complex128).

Custom type *Table is not a Go type but is supported by gotables to allow nested tables within table cells.

The list includes some aliases:-

[]byte and []uint8

func Uint8SliceEquals

func Uint8SliceEquals(slice1, slice2 []uint8) (bool, error)

Returns whether slice1 is equal to slice2.

Note: This could have been called ByteSliceEquals() with the same meaning.

Error information: in what way the slices are unequal.

See: bytes.Equal() for the builtin alternative function.

See: bytes.Compare() for the builtin comparison function.

func UtilBuildDateTime

func UtilBuildDateTime() (buildDateTime string)

Return a string with the build date/time and (seconds-ago) of the executable and where it is installed.

func UtilCanReadFromPipe

func UtilCanReadFromPipe() (bool, error)

Check to see if this program can read piped input on this machine.

func UtilCheckStringFlag

func UtilCheckStringFlag(name string, arg string, required bool) (exists bool, err error)

func UtilFilepathAbs

func UtilFilepathAbs(inputPath string) (path string, err error)

Handle Cygwin environment.

The problem:

cygwinPath := "/cygdrive/c/mypath/myfile"
windowsPath := filepath.Abs(cygwinPath)

returns: "C:/cygdrive/c/mypath/myfile"

It should return: "C:/mypath/myfile"

func UtilFormatSource

func UtilFormatSource(source string) (formattedSource string, err error)
Example

NOTE: ExampleGoFmtProgramString() required some careful tweaking to get it right. The test output reported spaces expected, but the actual output of GoFmtProgramString() has 5 tabs, which needed to be placed in the Output area. A larger example would have been very tedious to get right.

var err error

goProgramString :=
	`package main
import "os"
func main() {
i := 42
if i != 42 { os.Exit(1) }
}`

formattedGoProgramString, err := UtilFormatSource(goProgramString)
if err != nil {
	log.Println(err)
}

hasTabs := strings.Contains(formattedGoProgramString, "\t")
fmt.Printf("hasTabs = %t\n", hasTabs)

numTabs := strings.Count(formattedGoProgramString, "\t")
fmt.Printf("numTabs = %d\n", numTabs)

fmt.Println()

fmt.Println(formattedGoProgramString)
Output:

hasTabs = true
numTabs = 5

package main

import "os"

func main() {
	i := 42
	if i != 42 {
		os.Exit(1)
	}
}

func UtilFuncCaller

func UtilFuncCaller() string

Return the name of the function that called this function.

func UtilFuncCallerCaller

func UtilFuncCallerCaller() string

Return the name of the function that called the caller of this function.

func UtilFuncName

func UtilFuncName() string

Short function name with parentheses.

pkgName.funcName

becomes:

funcName()
Example
// Called from inside func ExampleFuncName()
fmt.Println(UtilFuncName())
Output:

ExampleUtilFuncName()

func UtilFuncNameFull

func UtilFuncNameFull() string

Full path of function source code with line number followed by full package name of function. Like this:

<mydrive>/golang/src/github.com/urban-wombat/gotables/util_test.go[39] github.com/urban-wombat/UtilTestFuncNameFull

func UtilFuncNameNoParens

func UtilFuncNameNoParens() string

Short function name with NO parentheses.

pkgName.funcName

becomes:

funcName
Example
// Called from inside func ExampleFuncNameNoParens()
fmt.Println(UtilFuncNameNoParens())
Output:

ExampleUtilFuncNameNoParens

func UtilFuncSource

func UtilFuncSource() string

Short source file name and line number. Like this:

util_test.go[39]

func UtilGulpFromPipe

func UtilGulpFromPipe() (string, error)

Read and return piped input as a string.

Beware: this blocks waiting for stdin.

stdin, err := UtilGulpFromPipe()

func UtilGulpFromPipeWithTimeout

func UtilGulpFromPipeWithTimeout(timeout time.Duration) (input string, err error)

Read and return piped input as a string.

This waits for stdin but only until timeout expires.

stdin, err := UtilGulpFromPipe(1 * time.Second)

func UtilIsCommandInstalled

func UtilIsCommandInstalled(commandName string) (bool, error)

Check whether commandName is installed on this machine.

func UtilPrintCaller

func UtilPrintCaller()

See 1: https://stackoverflow.com/questions/35212985/is-it-possible-get-information-about-caller-function-in-golang

See 2: http://moazzam-khan.com/blog/golang-get-the-function-callers-name

This is a blend of both (above URLs) examples. Provides:-

(1) The function name called.

(2) The function name of the caller.

(2) The file name[line number] at the call.

This is intentionally a print-only function because calling it from another function (other than the one being tracked) will change the calling information by nesting to an additional level.

func UtilPrintCallerCaller added in v0.17.0

func UtilPrintCallerCaller()

BEWARE: NOT PROPERLY TESTED!

See 1: https://stackoverflow.com/questions/35212985/is-it-possible-get-information-about-caller-function-in-golang

See 2: http://moazzam-khan.com/blog/golang-get-the-function-callers-name

This is a blend of both (above URLs) examples. Provides:-

(1) The function name called.

(2) The function name of the caller's caller.

(2) The file name[line number] at the call.

This is intentionally a print-only function because calling it from another function (other than the one being tracked) will change the calling information by nesting to an additional level.

func UtilProgName

func UtilProgName() string

func UtilRound

func UtilRound(val float64, places int) (rounded float64)

Round is a custom implementation for rounding values.

Round up if fraction is >= 0.5 otherwise round down.

From: https://medium.com/@edoardo849/mercato-how-to-build-an-effective-web-scraper-with-golang-e2918d279f49#.istjzw4nl

func UtilWordSize

func UtilWordSize() int

The word size (in bits) of the machine we're now running on. Typically 64 or 32 bits.

Or use: intBits := strconv.IntSize

Types

type SortKeyExported

type SortKeyExported struct {
	ColName  string
	ColType  string
	Reverse  bool
	SortFunc compareFunc
}

For GOB encoding and GOB decoding, which requires items to be exported.

type SortKeys

type SortKeys []sortKey

SortKeys is a slice of sortKey which facilitates multi-key ascending/descending sorting and searching.

type sortKey struct {
	colName  string
	colType  string
	reverse  bool	// true for descending sort/search
	sortFunc compareFunc
}

func (SortKeys) String

func (keys SortKeys) String() string

type Table

type Table struct {
	// contains filtered or unexported fields
}

func GobDecodeTable

func GobDecodeTable(buf []byte) (*Table, error)

Reconstruct a Table from a slice of []byte

Equivalent to NewTableFromGob()

Note: GOB encoding and decoding does not (yet) support nested tables or type time.Time.

func NewNilTable

func NewNilTable() *Table

Factory function to create an empty *Table that is not yet ready to use

The table is for use as zero value, a *Table that is a placeholder without being a Go nil

To make it usable, give it a table name: table.SetTableName("MyTableName")

In its unusable NilTable state, table.IsValidTable() will return false

var myTable *gotables.Table = gotables.NewNilTable()

Note: does not return an error. It cannot fail.

Example (CreateAndUse)
// We expect this to print a NilTable with syntax: []
var nilTable *Table = NewNilTable()
fmt.Println(nilTable)

// We expect this to be an invalid table
isValid, err := nilTable.IsValidTable()
fmt.Printf("isValid = %t\n", isValid)
fmt.Printf("err = %v\n", err)

// We expect any Set, Get or Append operation on the table to fail
err = nilTable.AppendRow()
fmt.Printf("err = %v\n", err)
err = nilTable.AppendCol("my_col", "string")
fmt.Printf("err = %v\n", err)

// This fails
err = nilTable.SetString("missing_col", 0, "my_string_value")
fmt.Printf("err = %v\n", err)
missing_col, err := nilTable.GetInt("missing_col", 0)
fmt.Printf("missing_col = %d\n", missing_col)
fmt.Printf("err = %v\n", err)

// Okay, now we will un-NilTable the NilTable
err = nilTable.SetName("NilTableNoLonger")
if err != nil {
	log.Println(err)
}
// Expecting: [NilTableNoLonger]
fmt.Println(nilTable)

// Now we can add a row and a col and set the cell value

err = nilTable.AppendCol("my_col", "string")
if err != nil {
	log.Println(err)
}

err = nilTable.AppendRow()
if err != nil {
	log.Println(err)
}

err = nilTable.SetString("my_col", 0, "my_string_value")
if err != nil {
	log.Println(err)
}

_ = nilTable.SetStructShape(true)
fmt.Println(nilTable)
Output:

[]

isValid = false
err = ERROR IsValidTable(): table has no name
err = table.AppendRow(): table is an unnamed NilTable. Call table.SetName() to un-Nil it
err = table.AppendCol(): table is an unnamed NilTable. Call table.SetName() to un-Nil it
err = table [] col does not exist: missing_col
missing_col = 0
err = table [] col does not exist: missing_col
[NilTableNoLonger]

[NilTableNoLonger]
my_col string = "my_string_value"

func NewTable

func NewTable(tableName string) (*Table, error)

Factory function to create an empty *Table

var myTable *gotables.Table
myTable, err = gotables.NewTable("My_Table")
if err != nil {
	panic(err)
}

func NewTableFromFile

func NewTableFromFile(fileName string) (*Table, error)

This function expects exactly ONE table in the file. Otherwise it's an error. If there's more than one table in the file, use NewTableFromFileByTableName() instead.

Example
tableString := `
	[MyTable]
	MyBool bool = true
	MyString string = "The answer to life, the universe and everything"
	MyInt int = 42
	`

table1, err := NewTableFromStringByTableName(tableString, "MyTable")
if err != nil {
	log.Println(err)
}

// For testing, we need to write this out to a file so we can read it back.
fileName := "ExampleNewTableFromFile.txt"
err = table1.WriteFile(fileName, 0644)
if err != nil {
	log.Println(err)
}

table2, err := NewTableFromFile(fileName)
if err != nil {
	log.Println(err)
}

fmt.Println(table2)

err = table2.SetStructShape(false)
if err != nil {
	log.Println(err)
}

fmt.Println(table2)
Output:

[MyTable]
MyBool bool = true
MyString string = "The answer to life, the universe and everything"
MyInt int = 42

[MyTable]
MyBool MyString                                          MyInt
bool   string                                              int
true   "The answer to life, the universe and everything"    42

func NewTableFromFileByTableName

func NewTableFromFileByTableName(fileName string, tableName string) (*Table, error)
Example
/*
	NewTableFromFileByTableName() is for when you want just one table from
	(possibly) multiple tables in a file, and you don't want to bother with
	NewTableSetFromFile().

	See also NewTableFromStringByTableName().
*/.
*/

tableSetString := `
	[MyTable]
	MyBool bool = true
	MyString string = "The answer to life, the universe and everything"
	MyInt int = 42

	[Fred]
	i
	int
	`

// For testing, we need to write this out to a file so we can read it back.
tableSet, err := NewTableSetFromString(tableSetString)
if err != nil {
	log.Println(err)
}
fileName := "ExampleNewTableFromFileByTableName.txt"
err = tableSet.WriteFile(fileName, 0644)
if err != nil {
	log.Println(err)
}

table, err := NewTableFromFileByTableName(fileName, "MyTable")
if err != nil {
	log.Println(err)
}

fmt.Println(table)
Output:

[MyTable]
MyBool bool = true
MyString string = "The answer to life, the universe and everything"
MyInt int = 42

func NewTableFromGob

func NewTableFromGob(buf []byte) (*Table, error)

Reconstruct a Table from a slice of []byte

Calls GobDecodeTable([]byte)

Note: GOB encoding and decoding does not (yet) support nested tables or type time.Time.

func NewTableFromJSON

func NewTableFromJSON(jsonString string) (table *Table, err error)
Example
//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))
var err error

tableString :=
	`[MyTable]
	i    u    f       t
	int  uint float32 time.Time
	1    2    3.3     2020-03-15T14:22:30Z
	4    5    6.6     2020-03-15T14:22:30.12345+17:00
	`
table1, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}
fmt.Println(table1)

var jsonString string
var buf bytes.Buffer

jsonString, err = table1.GetTableAsJSON()
if err != nil {
	fmt.Println(err)
}

// For readability.
err = json.Indent(&buf, []byte(jsonString), "", "  ")
if err != nil {
	fmt.Println(err)
}
_, _ = buf.WriteTo(os.Stdout)
fmt.Println()
fmt.Println()

table2, err := NewTableFromJSON(jsonString)
if err != nil {
	fmt.Println(err)
}
fmt.Println(table2)

equals, err := table2.Equals(table1)
if err != nil {
	fmt.Println(err)
}
fmt.Printf("table2.Equals(table1) == %t\n", equals)
Output:

[MyTable]
  i    u       f t
int uint float32 time.Time
  1    2     3.3 2020-03-15T14:22:30Z
  4    5     6.6 2020-03-15T14:22:30.12345+17:00

{
  "tableSetName": "",
  "tables": [
    {
      "tableName": "MyTable",
      "metadata": [
        {
          "i": "int"
        },
        {
          "u": "uint"
        },
        {
          "f": "float32"
        },
        {
          "t": "time.Time"
        }
      ],
      "data": [
        [
          {
            "i": 1
          },
          {
            "u": 2
          },
          {
            "f": 3.3
          },
          {
            "t": "2020-03-15T14:22:30Z"
          }
        ],
        [
          {
            "i": 4
          },
          {
            "u": 5
          },
          {
            "f": 6.6
          },
          {
            "t": "2020-03-15T14:22:30.12345+17:00"
          }
        ]
      ]
    }
  ]
}

[MyTable]
  i    u       f t
int uint float32 time.Time
  1    2     3.3 2020-03-15T14:22:30Z
  4    5     6.6 2020-03-15T14:22:30.12345+17:00

table2.Equals(table1) == true
Example (ZeroCols)

It is permitted to have zero cols.

//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))
var err error

tableString :=
	`[MyTable]
	`
table1, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table1)

var jsonString string
jsonString, err = table1.GetTableAsJSONIndent()
if err != nil {
	fmt.Println(err)
}

fmt.Println(jsonString)
fmt.Println()

table2, err := NewTableFromJSON(jsonString)
if err != nil {
	fmt.Println(err)
}

fmt.Println(table2)

equals, err := table2.Equals(table1)
if err != nil {
	fmt.Println(err)
}
fmt.Printf("table2.Equals(table1) == %t\n", equals)
Output:

[MyTable]

{
	"tableSetName": "",
	"tables": [
		{
			"tableName": "MyTable",
			"metadata": [],
			"data": []
		}
	]
}

[MyTable]

table2.Equals(table1) == true
Example (ZeroRows)

It is permitted to have zero rows.

//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))
var err error

tableString :=
	`[MyTable]
	i    u    f
	int  uint float32
	`
table1, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table1)

var jsonString string
var buf bytes.Buffer

jsonString, err = table1.GetTableAsJSON()
if err != nil {
	fmt.Println(err)
}

// For readability.
err = json.Indent(&buf, []byte(jsonString), "", "  ")
if err != nil {
	fmt.Println(err)
}
_, _ = buf.WriteTo(os.Stdout)

fmt.Println()

table2, err := NewTableFromJSON(jsonString)
if err != nil {
	fmt.Println(err)
}

fmt.Println(table2)

equals, err := table2.Equals(table1)
if err != nil {
	fmt.Println(err)
}
fmt.Printf("table2.Equals(table1) == %t\n", equals)
Output:

[MyTable]
  i    u       f
int uint float32

{
  "tableSetName": "",
  "tables": [
    {
      "tableName": "MyTable",
      "metadata": [
        {
          "i": "int"
        },
        {
          "u": "uint"
        },
        {
          "f": "float32"
        }
      ],
      "data": []
    }
  ]
}
[MyTable]
  i    u       f
int uint float32

table2.Equals(table1) == true

func NewTableFromJSONByTableName

func NewTableFromJSONByTableName(jsonString string, tableName string) (table *Table, err error)

func NewTableFromMetadata

func NewTableFromMetadata(tableName string, colNames []string, colTypes []string) (*Table, error)

table, err := gotables.NewTableFromMetadata("Moviegoers", []string{"Age", "Mothballs"}, []string{"int", "bool"})

func NewTableFromString

func NewTableFromString(s string) (*Table, error)

This function expects exactly ONE table in the string. Otherwise it's an error. If there's more than one table in the string, use NewTableFromStringByTableName() instead.

Example (Planets)
// mass:     Earth = 1 (relative to Earth)
// distance: Earth = 1 (relative to Earth - AU)
// http://www.windows2universe.org/our_solar_system/planets_table.html
tableString :=
	`[planets]
	name         mass distance moons index mnemonic
	string    float64  float64   int   int string
	"Mercury"   0.055      0.4     0     0 "my"
	"Venus"     0.815      0.7     0     1 "very"
	"Earth"     1.000      1.0     1     2 "elegant"
	"Mars"      0.107      1.5     2     3 "mother"
	"Jupiter" 318.000      5.2    79     4 "just"
	"Saturn"   95.000      9.5    82     5 "sat"
	"Uranus"   15.000     19.2    27     6 "upon"
	"Neptune"  17.000     30.6    13     7 "nine"
	"Pluto"     0.002     39.4     5     8 "porcupines"
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

// Simply echo it back out.
fmt.Println(table)

//	REINSTATE OPEN AND CLOSE COMMENTS
//		Notice that by default the columns of data are padded with spaces and numeric types
//		are right-aligned.
//		This reflects the opinion that human readability is important.
//		*Table.String() and *TableSet.String() call their underlying StringPadded() methods.
//		Where human readability is not important (with messaging or as a wire format) use:
//		*Table.StringUnpadded()
//		*TableSet.StringUnpadded()
//		StringUnpadded() is 3 to 4 times faster.
//		Reading a padded table string is only slightly slower (about 2.7% slower).
//	REINSTATE OPEN AND CLOSE COMMENTS

// For unpadded output:
fmt.Println(table.StringUnpadded())
Output:

[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Mercury"   0.055      0.4     0     0 "my"
"Venus"     0.815      0.7     0     1 "very"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Jupiter" 318.0        5.2    79     4 "just"
"Saturn"   95.0        9.5    82     5 "sat"
"Uranus"   15.0       19.2    27     6 "upon"
"Neptune"  17.0       30.6    13     7 "nine"
"Pluto"     0.002     39.4     5     8 "porcupines"

[planets]
name mass distance moons index mnemonic
string float64 float64 int int string
"Mercury" 0.055 0.4 0 0 "my"
"Venus" 0.815 0.7 0 1 "very"
"Earth" 1 1 1 2 "elegant"
"Mars" 0.107 1.5 2 3 "mother"
"Jupiter" 318 5.2 79 4 "just"
"Saturn" 95 9.5 82 5 "sat"
"Uranus" 15 19.2 27 6 "upon"
"Neptune" 17 30.6 13 7 "nine"
"Pluto" 0.002 39.4 5 8 "porcupines"
Example (Struct)
// A table literal. Sometimes easier than constructing a table programmatically.
tableString := `[MyTable]
		MyBool bool = true
		MyString string = "The answer to life, the universe and everything is forty-two."
		MyInt int = 42`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

// Print the table in its original struct shape.
fmt.Println(table)

// Now change its shape to tabular.
err = table.SetStructShape(false)
if err != nil {
	log.Println(err)
}

// The table is now printed as a single row of data.
fmt.Println(table)

// Note: The struct/tabular shape is for readability and has no impact on its internal structure.
Output:

[MyTable]
MyBool bool = true
MyString string = "The answer to life, the universe and everything is forty-two."
MyInt int = 42

[MyTable]
MyBool MyString                                                        MyInt
bool   string                                                            int
true   "The answer to life, the universe and everything is forty-two."    42
Example (UnicodeRuneLiterals)
var runesEqual string = `
[RunesEqual]
code     glyph  dec str
rune     rune   int string
'\u0000' '\x00'   0 ""
'\x61'   'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0007' '\a'     7 "\a"
'\u0008' '\b'     8 "\b"
'\u0009' '\t'     9 "\t"
'\u000A' '\n'    10 "\n"
'\u000B' '\v'    11 "\v"
'\u000C' '\f'    12 "\f"
'\u000D' '\r'    13 "\r"
'\u005C' '\\'    92 "\\"
'\u4E16' '世' 19990 "世"
'\u754C' '界' 30028 "界"
'\u0041' 'A'     65 "A"
'\u0042' 'B'     66 "A"
'\u0043' 'C'     67 "A"
'\x44'   'D'     68 "D"
'\u006D' 'm'    109 "m"
'z'      'z'    122 "z"
`

table, err := NewTableFromString(runesEqual)
if err != nil {
	log.Println(err)
}

fmt.Print("(1) Runes source table:")
fmt.Printf("%s\n", runesEqual)

fmt.Println("(2) Runes output table:")
fmt.Printf("%s", table)
Output:

(1) Runes source table:
[RunesEqual]
code     glyph  dec str
rune     rune   int string
'\u0000' '\x00'   0 ""
'\x61'   'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0007' '\a'     7 "\a"
'\u0008' '\b'     8 "\b"
'\u0009' '\t'     9 "\t"
'\u000A' '\n'    10 "\n"
'\u000B' '\v'    11 "\v"
'\u000C' '\f'    12 "\f"
'\u000D' '\r'    13 "\r"
'\u005C' '\\'    92 "\\"
'\u4E16' '世' 19990 "世"
'\u754C' '界' 30028 "界"
'\u0041' 'A'     65 "A"
'\u0042' 'B'     66 "A"
'\u0043' 'C'     67 "A"
'\x44'   'D'     68 "D"
'\u006D' 'm'    109 "m"
'z'      'z'    122 "z"

(2) Runes output table:
[RunesEqual]
code   glyph    dec str
rune   rune     int string
'\x00' '\x00'     0 ""
'a'    'a'       97 "a"
'a'    'a'       97 "a"
'a'    'a'       97 "a"
'a'    'a'       97 "a"
'\a'   '\a'       7 "\a"
'\b'   '\b'       8 "\b"
'\t'   '\t'       9 "\t"
'\n'   '\n'      10 "\n"
'\v'   '\v'      11 "\v"
'\f'   '\f'      12 "\f"
'\r'   '\r'      13 "\r"
'\\'   '\\'      92 "\\"
'世'    '世'    19990 "世"
'界'    '界'    30028 "界"
'A'    'A'       65 "A"
'B'    'B'       66 "A"
'C'    'C'       67 "A"
'D'    'D'       68 "D"
'm'    'm'      109 "m"
'z'    'z'      122 "z"
Example (UnicodeRuneLiteralsUnpadded)
var runesEqual string = `
[RunesEqual]
code     glyph  dec str
rune     rune   int string
'\u0000' '\x00'   0 ""
'\x61'   'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0007' '\a'     7 "\a"
'\u0008' '\b'     8 "\b"
'\u0009' '\t'     9 "\t"
'\u000A' '\n'    10 "\n"
'\u000B' '\v'    11 "\v"
'\u000C' '\f'    12 "\f"
'\u000D' '\r'    13 "\r"
'\u005C' '\\'    92 "\\"
'\u4E16' '世' 19990 "世"
'\u754C' '界' 30028 "界"
'\u0041' 'A'     65 "A"
'\u0042' 'B'     66 "A"
'\u0043' 'C'     67 "A"
'\x44'   'D'     68 "D"
'\u006D' 'm'    109 "m"
'z'      'z'    122 "z"
`

table, err := NewTableFromString(runesEqual)
if err != nil {
	log.Println(err)
}

fmt.Print("(1) Runes source table:")
fmt.Printf("%s\n", runesEqual)

fmt.Println("(2) Runes output table:")
fmt.Printf("%s", table.StringUnpadded())
Output:

(1) Runes source table:
[RunesEqual]
code     glyph  dec str
rune     rune   int string
'\u0000' '\x00'   0 ""
'\x61'   'a'     97 "a"
'\u0061' 'a'     97 "a"
'\u0007' '\a'     7 "\a"
'\u0008' '\b'     8 "\b"
'\u0009' '\t'     9 "\t"
'\u000A' '\n'    10 "\n"
'\u000B' '\v'    11 "\v"
'\u000C' '\f'    12 "\f"
'\u000D' '\r'    13 "\r"
'\u005C' '\\'    92 "\\"
'\u4E16' '世' 19990 "世"
'\u754C' '界' 30028 "界"
'\u0041' 'A'     65 "A"
'\u0042' 'B'     66 "A"
'\u0043' 'C'     67 "A"
'\x44'   'D'     68 "D"
'\u006D' 'm'    109 "m"
'z'      'z'    122 "z"

(2) Runes output table:
[RunesEqual]
code glyph dec str
rune rune int string
'\x00' '\x00' 0 ""
'a' 'a' 97 "a"
'a' 'a' 97 "a"
'\a' '\a' 7 "\a"
'\b' '\b' 8 "\b"
'\t' '\t' 9 "\t"
'\n' '\n' 10 "\n"
'\v' '\v' 11 "\v"
'\f' '\f' 12 "\f"
'\r' '\r' 13 "\r"
'\\' '\\' 92 "\\"
'世' '世' 19990 "世"
'界' '界' 30028 "界"
'A' 'A' 65 "A"
'B' 'B' 66 "A"
'C' 'C' 67 "A"
'D' 'D' 68 "D"
'm' 'm' 109 "m"
'z' 'z' 122 "z"

func NewTableFromStringByTableName

func NewTableFromStringByTableName(s string, tableName string) (*Table, error)

func NewTableFromStringMustMake

func NewTableFromStringMustMake(s string) *Table

This function expects exactly ONE table in the string. Otherwise it's an error. If there's more than one table in the string, use NewTableFromStringByTableName() instead.

On error, this function panics. It's for single-value contexts where you KNOW it will work.

func (*Table) AppendCol

func (table *Table) AppendCol(colName string, colType string) error

Append a column to this table.

err = myTable.AppendCol(headingName, headingType)
if err != nil {
	panic(err)
}

func (*Table) AppendColsFromTable

func (table *Table) AppendColsFromTable(fromTable *Table) error

Append all columns from fromTable to table.

Column order is ignored. Identical duplicate columns are ignored.

func (*Table) AppendRow

func (table *Table) AppendRow() error

All cells in the new added row will be set to their zero value, such as 0, "", or false. Note: Can append rows to an empty (no columns) table, and later append columns.

func (*Table) AppendRows

func (table *Table) AppendRows(howMany int) error

Note: Can append rows to an empty (no columns) table, and later append columns.

howMany may be 0 or more rows.

func (*Table) AppendRowsFromTable

func (toTable *Table) AppendRowsFromTable(fromTable *Table, firstRow int, lastRow int) error

func (*Table) AppendSortKey

func (table *Table) AppendSortKey(colName string) error

func (*Table) ColCount

func (table *Table) ColCount() int

func (*Table) ColIndex

func (table *Table) ColIndex(colName string) (int, error)

func (*Table) ColName

func (table *Table) ColName(colIndex int) (string, error)

Return the name of the column at this column index. Same as table.ColNameByColIndex(colIndex)

func (*Table) ColNameByColIndex

func (table *Table) ColNameByColIndex(colIndex int) (string, error)

Return the name of the column at this column index. Same as table.ColName(colIndex)

func (*Table) ColType

func (table *Table) ColType(colName string) (string, error)

func (*Table) ColTypeByColIndex

func (table *Table) ColTypeByColIndex(colIndex int) (string, error)

func (*Table) CompareRows

func (table *Table) CompareRows(rowIndex1 int, rowIndex2 int) (int, error)

Compare two rows using table sort keys.

Return -1 if rowIndex1 is less than rowIndex2.
Return  0 if rowIndex1 equals rowIndex2.
Return  1 if rowIndex1 is greater than rowIndex2.
Return -2 if error.

func (*Table) Copy

func (table *Table) Copy(copyRowsAlso bool) (*Table, error)

Create a copy of table, with or without copying its rows of data.

To copy some but not all rows, use NewTableFromRows()

func (*Table) DeleteCol

func (table *Table) DeleteCol(colName string) error

func (*Table) DeleteColByColIndex

func (table *Table) DeleteColByColIndex(colIndex int) error

func (*Table) DeleteRow

func (table *Table) DeleteRow(rowIndex int) error

func (*Table) DeleteRows

func (table *Table) DeleteRows(firstRowIndex int, lastRowIndex int) error

Delete rows from firstRowIndex to lastRowIndex inclusive. This means lastRowIndex will be deleted.

Example
tableString := `
	[items]
	item
	int
	0
	1
	2
	3
	4
	5
	6
	7
	8
	9
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)
if err != nil {
	log.Println(err)
}

if isValid, err := table.IsValidTable(); !isValid {
	log.Println(err)
}

err = table.DeleteRows(4, 6)
if isValid, err := table.IsValidTable(); !isValid {
	log.Println(err)
}

if err != nil {
	log.Println(err)
}

fmt.Println(table)
Output:

[items]
item
 int
   0
   1
   2
   3
   4
   5
   6
   7
   8
   9

[items]
item
 int
   0
   1
   2
   3
   7
   8
   9

func (*Table) DeleteRowsAll

func (table *Table) DeleteRowsAll() error

If table has any rows, delete them all. This is to deal simply with empty tables.

func (*Table) DeleteSortKey

func (table *Table) DeleteSortKey(keyName string) error

Delete a sort key by name.

func (*Table) Equals

func (table1 *Table) Equals(table2 *Table) (bool, error)
A fairy strict table comparison:
1 Column count must match.
2 Row count must match.
3 Column names must match.
4 Column types must match.
5 Rows order must match.
6 Cell values must match.
7 Table name must match.
8 Column order need NOT match.

Useful for testing.

func (*Table) GenerateTypeStruct

func (table *Table) GenerateTypeStruct() (string, error)

Generate a Go struct (as a string) for storing a gotables.Table as a slice of struct.

Compile the Go struct into your own programs.

See also: GenerateTypeStructSliceFromTable()

Source table:

[MyTable]
	  f b       i str       bb
float32 bool  int string    []byte
	4.4 true   32 "Hello!"  [3 2 1 0]
	5.5 true  -32 "Goodie!" [4 5 6 7 8]
	6.6 false   0 "Great!"  [0 1 2]

Generated Go struct:

type MyTable struct {
        f float32
        b bool
        i int
        str string
        bb []byte
}

func (*Table) GenerateTypeStructSliceFromTable

func (table *Table) GenerateTypeStructSliceFromTable() (string, error)
	Generate a Go function (as a string) to convert a gotables.Table to a slice of struct.

	Compile the Go function into your own programs.

	See also: GenerateTypeStruct()

	See also: GenerateTypeStructSliceFromTableSet()

	Source table:

		[MyTable]
		      f b       i str       bb
		float32 bool  int string    []byte
		    4.4 true   32 "Hello!"  [3 2 1 0]
		    5.5 true  -32 "Goodie!" [4 5 6 7 8]
		    6.6 false   0 "Great!"  [0 1 2]

	Previously-generated type struct - using GenerateTypeStruct()

		type MyTable struct {
		        f float32
		        b bool
		        i int
		        str string
		        bb []byte
		}

	Generated Go function - using GenerateTypeStructSliceFromTable()

        Automatically generated source code. DO NOT MODIFY. Generated 1:09 PM Friday 29 Sep 2017.

        Generate a slice of type MyTable struct from *gotables.Table [MyTable] for including in your code.

		func TypeStructSliceFromTable_MyTable(table *gotables.Table) ([]MyTable, error) {
		        if table == nil {
		                return nil, fmt.Errorf("TypeStructSliceFromTable_MyTable(slice []MyTable) slice is <nil>")
		        }

		        var MyTable []MyTable = make([]MyTable, table.RowCount())

		        for rowIndex := 0; rowIndex < table.RowCount(); rowIndex++ {
		                f, err := table.GetFloat32("f", rowIndex)
		                if err != nil {
		                        return nil, err
		                }
		                MyTable[rowIndex].f = f

		                b, err := table.GetBool("b", rowIndex)
		                if err != nil {
		                        return nil, err
		                }
		                MyTable[rowIndex].b = b

		                i, err := table.GetInt("i", rowIndex)
		                if err != nil {
		                        return nil, err
		                }
		                MyTable[rowIndex].i = i

		                str, err := table.GetString("str", rowIndex)
		                if err != nil {
		                        return nil, err
		                }
		                MyTable[rowIndex].str = str

		                bb, err := table.GetByteSlice("bb", rowIndex)
		                if err != nil {
		                        return nil, err
		                }
		                MyTable[rowIndex].bb = bb
		        }

		        return MyTable, nil
		}

	Snippets of code as they might appear in your own program:

		type MyTable struct {
		        f float32
		        b bool
		        i int
		        str string
		        bb []byte
		}

		var a []MyTable
		var err error
		a, err = TypeStructSliceFromTable_MyTable(table)
		if err != nil {
			panic(err)
		}
		for i := 0; i < len(a); i++ {
			fmt.Printf("a[%d] = %v\n", i, a[i])
		}

	Output:

		a[0] = {4.4 true 32 Hello! [3 2 1 0]}
		a[1] = {5.5 true -32 Goodie! [4 5 6 7 8]}
		a[2] = {6.6 false 0 Great! [0 1 2]}

func (*Table) GenerateTypeStructSliceToTable

func (table *Table) GenerateTypeStructSliceToTable() (string, error)
	Generate a Go function (as a string) to convert a slice of struct to a gotables.Table.

	Compile the Go function into your own programs.

	See also: GenerateTypeStruct()

	See also: GenerateTypeStructSliceFromTable() - convert in the opposite direction

	Source table:

		[MyTable]
		      f b       i str       bb
		float32 bool  int string    []byte
		    4.4 true   32 "Hello!"  [3 2 1 0]
		    5.5 true  -32 "Goodie!" [4 5 6 7 8]
		    6.6 false   0 "Great!"  [0 1 2]

	Previously-generated type struct - using GenerateTypeStruct()

		type MyTable struct {
		        f float32
		        b bool
		        i int
		        str string
		        bb []byte
		}

	Generated Go function - using GenerateTypeStructSliceToTable()

        Automatically generated source code. DO NOT MODIFY. Generated 1:12 PM Friday 29 Sep 2017.
        Generate a gotables Table [MyTable] from a slice of type struct []MyTable for including in your code.

		func TypeStructSliceToTable_MyTable(slice []MyTable) (*gotables.Table, error) {
		        if slice == nil {
		                return nil, fmt.Errorf("TypeStructSliceToTable_MyTable(slice []MyTable) slice is <nil>")
		        }

		        var err error

		        var seedTable string = `
		        [MyTable]
		        f float32
		        b bool
		        i int
		        str string
		        bb []byte
		        `
		        var table *gotables.Table
		        table, err = gotables.NewTableFromString(seedTable)
		        if err != nil {
		                return nil, err
		        }

		        for rowIndex := 0; rowIndex < len(slice); rowIndex++ {
		                err = table.AppendRow()
		                if err != nil {
		                        return nil, err
		                }

		                err = table.SetFloat32("f", rowIndex, slice[rowIndex].f)
		                if err != nil {
		                        return nil, err
		                }

		                err = table.SetBool("b", rowIndex, slice[rowIndex].b)
		                if err != nil {
		                        return nil, err
		                }

		                err = table.SetInt("i", rowIndex, slice[rowIndex].i)
		                if err != nil {
		                        return nil, err
		                }

		                err = table.SetString("str", rowIndex, slice[rowIndex].str)
		                if err != nil {
		                        return nil, err
		                }

		                err = table.SetByteSlice("bb", rowIndex, slice[rowIndex].bb)
		                if err != nil {
		                        return nil, err
		                }
		        }

		        return table, nil
		}

	Snippets of code as they might appear in your own program:

		type MyTable struct {
		        f float32
		        b bool
		        i int
		        str string
		        bb []byte
		}

		var a []MyTable
		var err error
		a, err = TypeStructSliceFromTable_MyTable(table)
		if err != nil {
			panic(err)
		}
		for i := 0; i < len(a); i++ {
			fmt.Printf("a[%d] = %v\n", i, a[i])
		}

		fmt.Println()
		a[2].i = 666
		a = append(a, MyTable{f: 7.7, b: true, i: 777, str: "Wonderful!!!", bb: []byte{9, 8, 7, 6, 5} })
		var x MyTable = MyTable{f: 8.8, b: true, i: 888, str: "Wonderful!!!", bb: []byte{1, 1, 1}}
		fmt.Printf("x = %v\n", x)
		a = append(a, x)

		var outTable *gotables.Table
		outTable, err = TypeStructSliceToTable_MyTable(a)
		if err != nil {
			panic(err)
		}

		fmt.Println()
		fmt.Println(outTable)

	Output:

		a[0] = {4.4 true 32 Hello! [3 2 1 0]}
		a[1] = {5.5 true -32 Goodie! [4 5 6 7 8]}
		a[2] = {6.6 false 0 Great! [0 1 2]}

		x = {8.8 true 888 Wonderful!!! [1 1 1]}

		[MyTable]
			  f b       i str            bb
		float32 bool  int string         []byte
			4.4 true   32 "Hello!"       [3 2 1 0]
			5.5 true  -32 "Goodie!"      [4 5 6 7 8]
			6.6 false 666 "Great!"       [0 1 2]
			7.7 true  777 "Wonderful!!!" [9 8 7 6 5]
			8.8 true  888 "Wonderful!!!" [1 1 1]

func (*Table) GetBool

func (table *Table) GetBool(colName string, rowIndex int) (val bool, err error)

Get bool table cell from colName at rowIndex

func (*Table) GetBoolByColIndex

func (table *Table) GetBoolByColIndex(colIndex int, rowIndex int) (val bool, err error)

Get bool table cell from colIndex at rowIndex

func (*Table) GetBoolByColIndexMustGet

func (table *Table) GetBoolByColIndexMustGet(colIndex int, rowIndex int) (val bool)
Get bool table cell from colIndex at rowIndex

Like its non-MustGet alternative GetBoolByColIndex(), but panics on error, and does not return an error.

func (*Table) GetBoolMustGet

func (table *Table) GetBoolMustGet(colName string, rowIndex int) (val bool)

Get bool table cell from colName at rowIndex

Like its non-MustGet alternative GetBool(), but panics on error, and does not return an error.

func (*Table) GetByte

func (table *Table) GetByte(colName string, rowIndex int) (val byte, err error)

Get byte table cell from colName at rowIndex

func (*Table) GetByteByColIndex

func (table *Table) GetByteByColIndex(colIndex int, rowIndex int) (val byte, err error)

Get byte table cell from colIndex at rowIndex

func (*Table) GetByteByColIndexMustGet

func (table *Table) GetByteByColIndexMustGet(colIndex int, rowIndex int) (val byte)
Get byte table cell from colIndex at rowIndex

Like its non-MustGet alternative GetByteByColIndex(), but panics on error, and does not return an error.

func (*Table) GetByteMustGet

func (table *Table) GetByteMustGet(colName string, rowIndex int) (val byte)

Get byte table cell from colName at rowIndex

Like its non-MustGet alternative GetByte(), but panics on error, and does not return an error.

func (*Table) GetByteSlice

func (table *Table) GetByteSlice(colName string, rowIndex int) (val []byte, err error)

Get []byte table cell from colName at rowIndex

func (*Table) GetByteSliceByColIndex

func (table *Table) GetByteSliceByColIndex(colIndex int, rowIndex int) (val []byte, err error)

Get []byte table cell from colIndex at rowIndex

func (*Table) GetByteSliceByColIndexMustGet

func (table *Table) GetByteSliceByColIndexMustGet(colIndex int, rowIndex int) (val []byte)
Get []byte table cell from colIndex at rowIndex

Like its non-MustGet alternative GetByteSliceByColIndex(), but panics on error, and does not return an error.

func (*Table) GetByteSliceMustGet

func (table *Table) GetByteSliceMustGet(colName string, rowIndex int) (val []byte)

Get []byte table cell from colName at rowIndex

Like its non-MustGet alternative GetByteSlice(), but panics on error, and does not return an error.

func (*Table) GetColInfoAsSlices

func (table *Table) GetColInfoAsSlices() ([]string, []string, error)

Return a slice of col names and a slice of col types:

colNames []string colTypes []string

func (*Table) GetColInfoAsTable

func (table *Table) GetColInfoAsTable() (*Table, error)

func (*Table) GetColValsAsStrings

func (table *Table) GetColValsAsStrings(colName string) ([]string, error)

Get column values (of any type) as a slice of strings.

func (*Table) GetFloat32

func (table *Table) GetFloat32(colName string, rowIndex int) (val float32, err error)

Get float32 table cell from colName at rowIndex

func (*Table) GetFloat32ByColIndex

func (table *Table) GetFloat32ByColIndex(colIndex int, rowIndex int) (val float32, err error)

Get float32 table cell from colIndex at rowIndex

func (*Table) GetFloat32ByColIndexMustGet

func (table *Table) GetFloat32ByColIndexMustGet(colIndex int, rowIndex int) (val float32)
Get float32 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetFloat32ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetFloat32MustGet

func (table *Table) GetFloat32MustGet(colName string, rowIndex int) (val float32)

Get float32 table cell from colName at rowIndex

Like its non-MustGet alternative GetFloat32(), but panics on error, and does not return an error.

func (*Table) GetFloat64

func (table *Table) GetFloat64(colName string, rowIndex int) (val float64, err error)

Get float64 table cell from colName at rowIndex

func (*Table) GetFloat64ByColIndex

func (table *Table) GetFloat64ByColIndex(colIndex int, rowIndex int) (val float64, err error)

Get float64 table cell from colIndex at rowIndex

func (*Table) GetFloat64ByColIndexMustGet

func (table *Table) GetFloat64ByColIndexMustGet(colIndex int, rowIndex int) (val float64)
Get float64 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetFloat64ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetFloat64MustGet

func (table *Table) GetFloat64MustGet(colName string, rowIndex int) (val float64)

Get float64 table cell from colName at rowIndex

Like its non-MustGet alternative GetFloat64(), but panics on error, and does not return an error.

func (*Table) GetInt

func (table *Table) GetInt(colName string, rowIndex int) (val int, err error)

Get int table cell from colName at rowIndex

func (*Table) GetInt16

func (table *Table) GetInt16(colName string, rowIndex int) (val int16, err error)

Get int16 table cell from colName at rowIndex

func (*Table) GetInt16ByColIndex

func (table *Table) GetInt16ByColIndex(colIndex int, rowIndex int) (val int16, err error)

Get int16 table cell from colIndex at rowIndex

func (*Table) GetInt16ByColIndexMustGet

func (table *Table) GetInt16ByColIndexMustGet(colIndex int, rowIndex int) (val int16)
Get int16 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetInt16ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetInt16MustGet

func (table *Table) GetInt16MustGet(colName string, rowIndex int) (val int16)

Get int16 table cell from colName at rowIndex

Like its non-MustGet alternative GetInt16(), but panics on error, and does not return an error.

func (*Table) GetInt32

func (table *Table) GetInt32(colName string, rowIndex int) (val int32, err error)

Get int32 table cell from colName at rowIndex

func (*Table) GetInt32ByColIndex

func (table *Table) GetInt32ByColIndex(colIndex int, rowIndex int) (val int32, err error)

Get int32 table cell from colIndex at rowIndex

func (*Table) GetInt32ByColIndexMustGet

func (table *Table) GetInt32ByColIndexMustGet(colIndex int, rowIndex int) (val int32)
Get int32 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetInt32ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetInt32MustGet

func (table *Table) GetInt32MustGet(colName string, rowIndex int) (val int32)

Get int32 table cell from colName at rowIndex

Like its non-MustGet alternative GetInt32(), but panics on error, and does not return an error.

func (*Table) GetInt64

func (table *Table) GetInt64(colName string, rowIndex int) (val int64, err error)

Get int64 table cell from colName at rowIndex

func (*Table) GetInt64ByColIndex

func (table *Table) GetInt64ByColIndex(colIndex int, rowIndex int) (val int64, err error)

Get int64 table cell from colIndex at rowIndex

func (*Table) GetInt64ByColIndexMustGet

func (table *Table) GetInt64ByColIndexMustGet(colIndex int, rowIndex int) (val int64)
Get int64 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetInt64ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetInt64MustGet

func (table *Table) GetInt64MustGet(colName string, rowIndex int) (val int64)

Get int64 table cell from colName at rowIndex

Like its non-MustGet alternative GetInt64(), but panics on error, and does not return an error.

func (*Table) GetInt8

func (table *Table) GetInt8(colName string, rowIndex int) (val int8, err error)

Get int8 table cell from colName at rowIndex

func (*Table) GetInt8ByColIndex

func (table *Table) GetInt8ByColIndex(colIndex int, rowIndex int) (val int8, err error)

Get int8 table cell from colIndex at rowIndex

func (*Table) GetInt8ByColIndexMustGet

func (table *Table) GetInt8ByColIndexMustGet(colIndex int, rowIndex int) (val int8)
Get int8 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetInt8ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetInt8MustGet

func (table *Table) GetInt8MustGet(colName string, rowIndex int) (val int8)

Get int8 table cell from colName at rowIndex

Like its non-MustGet alternative GetInt8(), but panics on error, and does not return an error.

func (*Table) GetIntByColIndex

func (table *Table) GetIntByColIndex(colIndex int, rowIndex int) (val int, err error)

Get int table cell from colIndex at rowIndex

func (*Table) GetIntByColIndexMustGet

func (table *Table) GetIntByColIndexMustGet(colIndex int, rowIndex int) (val int)
Get int table cell from colIndex at rowIndex

Like its non-MustGet alternative GetIntByColIndex(), but panics on error, and does not return an error.

func (*Table) GetIntMustGet

func (table *Table) GetIntMustGet(colName string, rowIndex int) (val int)

Get int table cell from colName at rowIndex

Like its non-MustGet alternative GetInt(), but panics on error, and does not return an error.

func (*Table) GetRune

func (table *Table) GetRune(colName string, rowIndex int) (val rune, err error)

Get rune table cell from colName at rowIndex

func (*Table) GetRuneByColIndex

func (table *Table) GetRuneByColIndex(colIndex int, rowIndex int) (val rune, err error)

Get rune table cell from colIndex at rowIndex

func (*Table) GetRuneByColIndexMustGet

func (table *Table) GetRuneByColIndexMustGet(colIndex int, rowIndex int) (val rune)
Get rune table cell from colIndex at rowIndex

Like its non-MustGet alternative GetRuneByColIndex(), but panics on error, and does not return an error.

func (*Table) GetRuneMustGet

func (table *Table) GetRuneMustGet(colName string, rowIndex int) (val rune)

Get rune table cell from colName at rowIndex

Like its non-MustGet alternative GetRune(), but panics on error, and does not return an error.

func (*Table) GetSortKeysAsTable

func (thisTable *Table) GetSortKeysAsTable() (*Table, error)

Returns a copy of the sort keys as a Table. Useful for debugging.

Example
tableString :=
	`[changes]
	user     language    lines
	string   string        int
	"gri"    "Go"          100
	"ken"    "C"           150
	"glenda" "Go"          200
	"rsc"    "Go"          200
	"r"      "Go"          100
	"ken"    "Go"          200
	"dmr"    "C"           100
	"r"      "C"           150
	"gri"    "Smalltalk"    80
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

// Sort the table by user but reverse lines.
err = table.SetSortKeys("user", "lines")
if err != nil {
	log.Println(err)
}

err = table.SetSortKeysReverse("lines")
if err != nil {
	log.Println(err)
}

fmt.Println("(1) GetSortKeysAsTable():")
sortKeysTable, err := table.GetSortKeysAsTable()
if err != nil {
	log.Println(err)
}
fmt.Println(sortKeysTable)

err = table.Sort()
if err != nil {
	log.Println(err)
}

fmt.Println("(2) Sort by user but reverse lines:")
fmt.Println(table)
Output:

(1) GetSortKeysAsTable():
[SortKeys]
index colName colType  reverse
  int string  string   bool
    0 "user"  "string" false
    1 "lines" "int"    true

(2) Sort by user but reverse lines:
[changes]
user     language    lines
string   string        int
"dmr"    "C"           100
"glenda" "Go"          200
"gri"    "Go"          100
"gri"    "Smalltalk"    80
"ken"    "Go"          200
"ken"    "C"           150
"r"      "C"           150
"r"      "Go"          100
"rsc"    "Go"          200

func (*Table) GetString

func (table *Table) GetString(colName string, rowIndex int) (val string, err error)

Get string table cell from colName at rowIndex

func (*Table) GetStringByColIndex

func (table *Table) GetStringByColIndex(colIndex int, rowIndex int) (val string, err error)

Get string table cell from colIndex at rowIndex

func (*Table) GetStringByColIndexMustGet

func (table *Table) GetStringByColIndexMustGet(colIndex int, rowIndex int) (val string)
Get string table cell from colIndex at rowIndex

Like its non-MustGet alternative GetStringByColIndex(), but panics on error, and does not return an error.

func (*Table) GetStringMustGet

func (table *Table) GetStringMustGet(colName string, rowIndex int) (val string)

Get string table cell from colName at rowIndex

Like its non-MustGet alternative GetString(), but panics on error, and does not return an error.

func (*Table) GetTable

func (table *Table) GetTable(colName string, rowIndex int) (val *Table, err error)

Get *Table table cell from colName at rowIndex

Example (CellTableInStruct)
// A table literal. Sometimes easier than constructing a table programmatically.
tableString := `[MyTable]
		MyBool bool = true
		MyString string = "The answer to life, the universe and everything."
		MyInt int = 42
		MyTable *Table = [CellTable]
		MyTable2 *Table = [CellTable2]
		`
// Note 1: The only string form of a table cell containing a *Table is its table name in square brackets.
// Note 2: To get a table cell *Table as a string, first retrieve it to a variable.
// Note 3: It is parsed into an empty table with the name specified.

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

myTable, err := table.GetTable("MyTable", 0)
if err != nil {
	log.Println(err)
}

err = myTable.AppendRow()
if err != nil {
	log.Println(err)
}

err = myTable.AppendCol("msg", "string")
if err != nil {
	log.Println(err)
}

err = myTable.SetString("msg", 0, "I am in a table in a cell!")
if err != nil {
	log.Println(err)
}

err = myTable.SetStructShape(true)
if err != nil {
	log.Println(err)
}

fmt.Println(myTable)

// Note: The struct/tabular shape is for readability and has no impact on its internal structure.
Output:

[MyTable]
MyBool bool = true
MyString string = "The answer to life, the universe and everything."
MyInt int = 42
MyTable *Table = [CellTable]
MyTable2 *Table = [CellTable2]

[CellTable]
msg string = "I am in a table in a cell!"
Example (CellTableInTabular)
// A table literal. Sometimes easier than constructing a table programmatically.
tableString := `[MyTable]
		MyBool MyString                                           MyInt MyTable     MyTable2
		bool   string                                               int *Table      *Table
		true   "The answer to life, the universe and everything."    42 [CellTable] [CellTable2]
		`
// Note 1: The only string form of a table cell containing a *Table is its table name in square brackets.
// Note 2: To get a table cell *Table as a string, first retrieve it to a variable.
// Note 3: It is parsed into an empty table with the name specified.

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

err = table.SetStructShape(false)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

myTable, err := table.GetTable("MyTable", 0)
if err != nil {
	log.Println(err)
}

err = myTable.AppendRow()
if err != nil {
	log.Println(err)
}

err = myTable.AppendCol("msg", "string")
if err != nil {
	log.Println(err)
}

err = myTable.SetString("msg", 0, "I am in a table in a cell!")
if err != nil {
	log.Println(err)
}

err = myTable.SetStructShape(true)
if err != nil {
	log.Println(err)
}

fmt.Println(myTable)

// Note: The struct/tabular shape is for readability and has no impact on its internal structure.
Output:

[MyTable]
MyBool MyString                                           MyInt MyTable     MyTable2
bool   string                                               int *Table      *Table
true   "The answer to life, the universe and everything."    42 [CellTable] [CellTable2]

[CellTable]
msg string = "I am in a table in a cell!"

func (*Table) GetTableAsCSV

func (table *Table) GetTableAsCSV(optionalSubstituteHeadingNames ...string) (string, error)

Return a table as a comma separated variables for spreadsheets.

optionalSubstituteHeadingNames: Leave empty or provide a []string of names of length table.ColCount()

See: https://en.wikipedia.org/wiki/Comma-separated_values

Example
tableString :=
	`[ForCSV]
	first_name  last_name   username    i   f64     b       f32     commas  quotes    runes end
	string      string      string      int float64 bool    float32 string  string    rune  string
	"Rob"       "Pike"      "rob"       1   1.1     true    NaN     ",end"  "\"xyz\"" '本'  "end"
	"Ken"       "Thompson"  "ken"       3   NaN     true    3.3     "beg,"  "'abc'"   '\''  "end"
	"Robert"    "Griesemer" "gri"       5   5.5     true    NaN     "m,d"   " \"\" "  ' '   "end"
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println("gotables table we wish to convert to CSV ...")
fmt.Println(table)

var csv string
csv, err = table.GetTableAsCSV()
if err != nil {
	log.Println(err)
}

fmt.Println("gotables table converted to CSV ...")
fmt.Println(csv)

optionalSubstituteHeadingNames := []string{"F Name", "L Name", "", "i", "f64", "bool", "f32", "Commas", "Quotes", "Runes", "end"}
csv, err = table.GetTableAsCSV(optionalSubstituteHeadingNames...)
if err != nil {
	log.Println(err)
}

fmt.Println("gotables table converted to CSV with user-provided optional heading names ...")
fmt.Println(csv)
Output:

gotables table we wish to convert to CSV ...
[ForCSV]
first_name last_name   username   i     f64 b        f32 commas quotes    runes end
string     string      string   int float64 bool float32 string string    rune  string
"Rob"      "Pike"      "rob"      1     1.1 true     NaN ",end" "\"xyz\"" '本'   "end"
"Ken"      "Thompson"  "ken"      3     NaN true     3.3 "beg," "'abc'"   '\''  "end"
"Robert"   "Griesemer" "gri"      5     5.5 true     NaN "m,d"  " \"\" "  ' '   "end"

gotables table converted to CSV ...
first_name,last_name,username,i,f64,b,f32,commas,quotes,runes,end
Rob,Pike,rob,1,1.1,true,,",end","""xyz""",本,end
Ken,Thompson,ken,3,,true,3.3,"beg,",'abc',',end
Robert,Griesemer,gri,5,5.5,true,,"m,d"," """" "," ",end

gotables table converted to CSV with user-provided optional heading names ...
F Name,L Name,username,i,f64,bool,f32,Commas,Quotes,Runes,end
Rob,Pike,rob,1,1.1,true,,",end","""xyz""",本,end
Ken,Thompson,ken,3,,true,3.3,"beg,",'abc',',end
Robert,Griesemer,gri,5,5.5,true,,"m,d"," """" "," ",end

func (*Table) GetTableAsJSON

func (table *Table) GetTableAsJSON() (jsonString string, err error)
Example (NestedTables)
//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))
var err error
var table1 *Table

var tableString string
tableString = `
	[TypesGalore22]
    i   s      right
    int string *Table
    0   "abc"  []
    1   "xyz"  []
    2   "ssss" []
    3   "xxxx" []
    4   "yyyy" []
    `
table1, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

// Now create and set some table cell tables.
right0 := `
	[right0]
	i int = 32`

right1 := `
	[right1]
	s string = "thirty-two"`

right2 := `
	[right2]
	x	y	z
	int	int	int
	1	2	3
	4	5	6
	7	8	9`

right3 := `
	[right3]
	f float32 = 88.8`

right4 := `
	[right4]
	t1 *Table = []`

table1.SetTableMustSet("right", 0, NewTableFromStringMustMake(right0))
table1.SetTableMustSet("right", 1, NewTableFromStringMustMake(right1))
table1.SetTableMustSet("right", 2, NewTableFromStringMustMake(right2))
table1.SetTableMustSet("right", 3, NewTableFromStringMustMake(right3))
table1.SetTableMustSet("right", 4, NewTableFromStringMustMake(right4))

var jsonString string
//where("***CALLING** NewTableFromJSON() ...")
jsonString, err = table1.GetTableAsJSON()
if err != nil {
	log.Println(err)
}

fmt.Println("Print as is:")
fmt.Println()
fmt.Println(jsonString)
fmt.Println()

fmt.Println("Print indented for readability:")
fmt.Println()
var out bytes.Buffer
err = json.Indent(&out, []byte(jsonString), "", "\t")
if err != nil {
	log.Println(err)
}
_, _ = out.WriteTo(os.Stdout)

// Now let's get it back from JSON into *Table
table2, err := NewTableFromJSON(jsonString)
if err != nil {
	log.Println(err)
}

fmt.Println()
fmt.Println()
fmt.Println(table2)
Output:

Print as is:

{"tableSetName":"","tables":[{"tableName":"TypesGalore22","metadata":[{"i":"int"},{"s":"string"},{"right":"*Table"}],"data":[[{"i":0},{"s":"abc"},{"right":{"tableName":"right0","isStructShape":true,"metadata":[{"i":"int"}],"data":[[{"i":32}]]}}],[{"i":1},{"s":"xyz"},{"right":{"tableName":"right1","isStructShape":true,"metadata":[{"s":"string"}],"data":[[{"s":"thirty-two"}]]}}],[{"i":2},{"s":"ssss"},{"right":{"tableName":"right2","metadata":[{"x":"int"},{"y":"int"},{"z":"int"}],"data":[[{"x":1},{"y":2},{"z":3}],[{"x":4},{"y":5},{"z":6}],[{"x":7},{"y":8},{"z":9}]]}}],[{"i":3},{"s":"xxxx"},{"right":{"tableName":"right3","isStructShape":true,"metadata":[{"f":"float32"}],"data":[[{"f":88.8}]]}}],[{"i":4},{"s":"yyyy"},{"right":{"tableName":"right4","isStructShape":true,"metadata":[{"t1":"*Table"}],"data":[[{"t1":null}]]}}]]}]}

Print indented for readability:

{
	"tableSetName": "",
	"tables": [
		{
			"tableName": "TypesGalore22",
			"metadata": [
				{
					"i": "int"
				},
				{
					"s": "string"
				},
				{
					"right": "*Table"
				}
			],
			"data": [
				[
					{
						"i": 0
					},
					{
						"s": "abc"
					},
					{
						"right": {
							"tableName": "right0",
							"isStructShape": true,
							"metadata": [
								{
									"i": "int"
								}
							],
							"data": [
								[
									{
										"i": 32
									}
								]
							]
						}
					}
				],
				[
					{
						"i": 1
					},
					{
						"s": "xyz"
					},
					{
						"right": {
							"tableName": "right1",
							"isStructShape": true,
							"metadata": [
								{
									"s": "string"
								}
							],
							"data": [
								[
									{
										"s": "thirty-two"
									}
								]
							]
						}
					}
				],
				[
					{
						"i": 2
					},
					{
						"s": "ssss"
					},
					{
						"right": {
							"tableName": "right2",
							"metadata": [
								{
									"x": "int"
								},
								{
									"y": "int"
								},
								{
									"z": "int"
								}
							],
							"data": [
								[
									{
										"x": 1
									},
									{
										"y": 2
									},
									{
										"z": 3
									}
								],
								[
									{
										"x": 4
									},
									{
										"y": 5
									},
									{
										"z": 6
									}
								],
								[
									{
										"x": 7
									},
									{
										"y": 8
									},
									{
										"z": 9
									}
								]
							]
						}
					}
				],
				[
					{
						"i": 3
					},
					{
						"s": "xxxx"
					},
					{
						"right": {
							"tableName": "right3",
							"isStructShape": true,
							"metadata": [
								{
									"f": "float32"
								}
							],
							"data": [
								[
									{
										"f": 88.8
									}
								]
							]
						}
					}
				],
				[
					{
						"i": 4
					},
					{
						"s": "yyyy"
					},
					{
						"right": {
							"tableName": "right4",
							"isStructShape": true,
							"metadata": [
								{
									"t1": "*Table"
								}
							],
							"data": [
								[
									{
										"t1": null
									}
								]
							]
						}
					}
				]
			]
		}
	]
}

[TypesGalore22]
  i s      right
int string *Table
  0 "abc"  [right0]
  1 "xyz"  [right1]
  2 "ssss" [right2]
  3 "xxxx" [right3]
  4 "yyyy" [right4]
Example (NestedTablesCircularReference)
//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))
var err error
var table *Table

/*
	A table with value [] will result in a NilTable with no table name.
	To make the table usable, give it a table name.
*/	*/

var tableString string
tableString = `
	[SameTableReference]
    left	i   s      right
    *Table	int string *Table
    []		42  "abc"  [] 
    `
table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println("This should fail: We are assigning the same table as the parent.")
table.SetTableMustSet("right", 0, table) // table already exists (at the top level)
fmt.Printf("%s", table)
_, err = table.GetTableAsJSON()
if err != nil {
	// Error prints here.
	fmt.Println(err)
}
fmt.Println()

fmt.Println("Now try again with a COPY of the same table, which will have a new reference.")
var jsonString string
var tableCopy *Table
tableCopy, err = table.Copy(true)
if err != nil {
	// No error to print here.
	fmt.Println(err)
}
err = tableCopy.SetName("TableCopy")
if err != nil {
	fmt.Println(err)
}
fmt.Println("By the way, don't try to set table 'right' to <nil>. Not allowed. Must use an actual *Table reference.")
err = tableCopy.SetTable("right", 0, nil) // Not allowed. Must use an actual *Table reference.
if err != nil {
	fmt.Println(err)
}
err = tableCopy.SetTable("right", 0, NewNilTable()) // Otherwise this is another circular reference.
if err != nil {
	fmt.Println(err)
}
fmt.Printf("%s", tableCopy)
fmt.Println()

fmt.Println("This should succeed: We are assigning a DIFFERENT table (same contents doesn't matter).")
table.SetTableMustSet("right", 0, tableCopy) // Different table reference.
fmt.Printf("%s", table)
jsonString, err = table.GetTableAsJSON()
if err != nil {
	fmt.Println(err)
}
fmt.Println()

fmt.Println("Print as is:")
jsonString, err = table.GetTableAsJSON()
if err != nil {
	fmt.Println(err)
}
fmt.Println(jsonString)
fmt.Println()

fmt.Println("Print indented for readability:")
jsonString, err = table.GetTableAsJSONIndent()
if err != nil {
	fmt.Println(err)
}
fmt.Println(jsonString)

fmt.Println()

fmt.Println("(1) This should fail: We are assigning the same table to multiple cells.")
table.SetTableMustSet("left", 0, tableCopy) // Different table reference.
fmt.Printf("%s", table)
jsonString, err = table.GetTableAsJSON()
if err != nil {
	// Prints error.
	fmt.Println(err)
}
fmt.Println()

fmt.Println("(2) This should fail: We are assigning the same table to multiple cells.")
valid, err := table.IsValidTableNesting()
fmt.Printf("table.IsValidTableNesting(): valid = %t\n", valid)
if err != nil {
	// Prints error.
	fmt.Println(err)
}
Output:

This should fail: We are assigning the same table as the parent.
[SameTableReference]
left     i s      right
*Table int string *Table
[]      42 "abc"  [SameTableReference]
getTableAsJSON_recursive(): circular reference in table [SameTableReference]: a reference to table [SameTableReference] already exists

Now try again with a COPY of the same table, which will have a new reference.
By the way, don't try to set table 'right' to <nil>. Not allowed. Must use an actual *Table reference.
SetTable(right, 0, val): table [TableCopy] col right expecting val of type *Table, not: <nil> [use NewNilTable() instead of <nil>]
[TableCopy]
left     i s      right
*Table int string *Table
[]      42 "abc"  []

This should succeed: We are assigning a DIFFERENT table (same contents doesn't matter).
[SameTableReference]
left     i s      right
*Table int string *Table
[]      42 "abc"  [TableCopy]

Print as is:
{"tableSetName":"","tables":[{"tableName":"SameTableReference","metadata":[{"left":"*Table"},{"i":"int"},{"s":"string"},{"right":"*Table"}],"data":[[{"left":null},{"i":42},{"s":"abc"},{"right":{"tableName":"TableCopy","metadata":[{"left":"*Table"},{"i":"int"},{"s":"string"},{"right":"*Table"}],"data":[[{"left":null},{"i":42},{"s":"abc"},{"right":null}]]}}]]}]}

Print indented for readability:
{
	"tableSetName": "",
	"tables": [
		{
			"tableName": "SameTableReference",
			"metadata": [
				{
					"left": "*Table"
				},
				{
					"i": "int"
				},
				{
					"s": "string"
				},
				{
					"right": "*Table"
				}
			],
			"data": [
				[
					{
						"left": null
					},
					{
						"i": 42
					},
					{
						"s": "abc"
					},
					{
						"right": {
							"tableName": "TableCopy",
							"metadata": [
								{
									"left": "*Table"
								},
								{
									"i": "int"
								},
								{
									"s": "string"
								},
								{
									"right": "*Table"
								}
							],
							"data": [
								[
									{
										"left": null
									},
									{
										"i": 42
									},
									{
										"s": "abc"
									},
									{
										"right": null
									}
								]
							]
						}
					}
				]
			]
		}
	]
}

(1) This should fail: We are assigning the same table to multiple cells.
[SameTableReference]
left          i s      right
*Table      int string *Table
[TableCopy]  42 "abc"  [TableCopy]
getTableAsJSON_recursive(): circular reference in table [SameTableReference]: a reference to table [TableCopy] already exists

(2) This should fail: We are assigning the same table to multiple cells.
table.IsValidTableNesting(): valid = false
isValidTableNesting_recursive(): circular reference in table [SameTableReference]: a reference to table [TableCopy] already exists

func (*Table) GetTableAsJSONIndent

func (table *Table) GetTableAsJSONIndent() (jsonStringIndented string, err error)

func (*Table) GetTableByColIndex

func (table *Table) GetTableByColIndex(colIndex int, rowIndex int) (val *Table, err error)

Get *Table table cell from colIndex at rowIndex

func (*Table) GetTableByColIndexMustGet

func (table *Table) GetTableByColIndexMustGet(colIndex int, rowIndex int) (val *Table)
Get *Table table cell from colIndex at rowIndex

Like its non-MustGet alternative GetTableByColIndex(), but panics on error, and does not return an error.

func (*Table) GetTableMustGet

func (table *Table) GetTableMustGet(colName string, rowIndex int) (val *Table)

Get *Table table cell from colName at rowIndex

Like its non-MustGet alternative GetTable(), but panics on error, and does not return an error.

func (*Table) GetTime

func (table *Table) GetTime(colName string, rowIndex int) (val time.Time, err error)

Get time.Time table cell from colName at rowIndex

Example
//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))

const rowIndex int = 0 // Always row 0 for struct shaped tables

var err error
var table *Table
var colIndex int

// RFC 3339
var tableString string = `[TimeTable]
	t0 time.Time = 2020-03-15T14:22:30Z
	t1 time.Time = 2020-03-15T14:22:30+17:00
	t2 time.Time = 2020-03-15T14:22:30-17:00
	t3 time.Time = 2020-03-15T14:22:30.12345Z
	t4 time.Time = 2020-03-15T14:22:30.12345+17:00
	t5 time.Time = 2020-03-15T14:22:30.12345-17:00
	`
table, err = NewTableFromString(tableString)
if err != nil {
	fmt.Println(err)
}
fmt.Println(table)

fmt.Println("AppendCol() initialises new col with the time.Time zero val: MinTime")
err = table.AppendCol("t6", "time.Time")
if err != nil {
	fmt.Println(err)
}
fmt.Println(table)

// Here are the time.Date() function arguments:
// func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time

fmt.Println("Set it to 2020 last day at 10pm")
// 2020 last day at 10pm
err = table.SetTime("t6", rowIndex, time.Date(2020, time.December, 31, 22, 0, 0, 0, time.UTC))
if err != nil {
	fmt.Println(err)
}
fmt.Println(table)

fmt.Println("Add an hour")
var t time.Time
t, err = table.GetTime("t6", rowIndex)
if err != nil {
	fmt.Println(err)
}
t = t.Add(time.Hour)
fmt.Printf("t = %v\n", t)
err = table.SetTime("t6", rowIndex, t)
if err != nil {
	fmt.Println(err)
}
fmt.Println(table)

fmt.Println("Append col t7 and set it to 2020 last day at 11:59pm and 1 nanosecond before midnight")
// 2020 last day at 11:59pm and 1 nanosecond before midnight
// There are 1,000,000,000 nanoseconds in a second
err = table.AppendCol("t7", "time.Time")
if err != nil {
	fmt.Println(err)
}
colIndex = 7
err = table.SetTimeByColIndex(colIndex, rowIndex, time.Date(2020, time.December, 31, 23, 59, 59, 999999999, time.UTC))
if err != nil {
	fmt.Println(err)
}
fmt.Println(table)

fmt.Println("Add a nanosecond")
t, err = table.GetTimeByColIndex(colIndex, rowIndex)
if err != nil {
	fmt.Println(err)
}
t = t.Add(time.Nanosecond)
fmt.Printf("t = %v\n", t)
err = table.SetTimeByColIndex(colIndex, rowIndex, t)
if err != nil {
	fmt.Println(err)
}
fmt.Println(table)

fmt.Println("AppendCol() and set it to gotables.MinTime")
// MinTime is a global variable defined in gotables.go
err = table.AppendCol("minTime", "time.Time")
if err != nil {
	fmt.Println(err)
}
err = table.SetTime("minTime", 0, MinTime)

fmt.Println("AppendCol() and set it to gotables.MaxTime")
// MaxTime is a global variable defined in gotables.go
err = table.AppendCol("maxTime", "time.Time")
if err != nil {
	fmt.Println(err)
}
err = table.SetTime("maxTime", 0, MaxTime)
fmt.Println(table)

fmt.Println("AppendCol() and set it to a parsed time literal string")
fmt.Println("time.RFC3339 is defined in the time package")
// From https://golang.org/pkg/time/#example_Parse:
// Some valid layouts are invalid time values, due to format specifiers
// such as _ for space padding and Z for zone information.
// For example the RFC3339 layout 2006-01-02T15:04:05Z07:00
// contains both Z and a time zone offset in order to handle both valid options:
// 2006-01-02T15:04:05Z
// 2006-01-02T15:04:05+07:00
// t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
// t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05+07:00")
err = table.AppendCol("myTime", "time.Time")
if err != nil {
	fmt.Println(err)
}
var myTimeString string = "2020-03-22T13:30:00.0+11:00"
var myTime time.Time
myTime, err = time.Parse(time.RFC3339, myTimeString)
if err != nil {
	fmt.Println(err)
}
err = table.SetTime("myTime", 0, myTime)
if err != nil {
	fmt.Println(err)
}
fmt.Println(table)
Output:

[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00

AppendCol() initialises new col with the time.Time zero val: MinTime
[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00
t6 time.Time = 0001-01-01T00:00:00Z

Set it to 2020 last day at 10pm
[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00
t6 time.Time = 2020-12-31T22:00:00Z

Add an hour
t = 2020-12-31 23:00:00 +0000 UTC
[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00
t6 time.Time = 2020-12-31T23:00:00Z

Append col t7 and set it to 2020 last day at 11:59pm and 1 nanosecond before midnight
[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00
t6 time.Time = 2020-12-31T23:00:00Z
t7 time.Time = 2020-12-31T23:59:59.999999999Z

Add a nanosecond
t = 2021-01-01 00:00:00 +0000 UTC
[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00
t6 time.Time = 2020-12-31T23:00:00Z
t7 time.Time = 2021-01-01T00:00:00Z

AppendCol() and set it to gotables.MinTime
AppendCol() and set it to gotables.MaxTime
[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00
t6 time.Time = 2020-12-31T23:00:00Z
t7 time.Time = 2021-01-01T00:00:00Z
minTime time.Time = 0001-01-01T00:00:00Z
maxTime time.Time = 292277024627-12-07T02:30:07.999999999+11:00

AppendCol() and set it to a parsed time literal string
time.RFC3339 is defined in the time package
[TimeTable]
t0 time.Time = 2020-03-15T14:22:30Z
t1 time.Time = 2020-03-15T14:22:30+17:00
t2 time.Time = 2020-03-15T14:22:30-17:00
t3 time.Time = 2020-03-15T14:22:30.12345Z
t4 time.Time = 2020-03-15T14:22:30.12345+17:00
t5 time.Time = 2020-03-15T14:22:30.12345-17:00
t6 time.Time = 2020-12-31T23:00:00Z
t7 time.Time = 2021-01-01T00:00:00Z
minTime time.Time = 0001-01-01T00:00:00Z
maxTime time.Time = 292277024627-12-07T02:30:07.999999999+11:00
myTime time.Time = 2020-03-22T13:30:00+11:00

func (*Table) GetTimeByColIndex

func (table *Table) GetTimeByColIndex(colIndex int, rowIndex int) (val time.Time, err error)

Get time.Time table cell from colIndex at rowIndex

func (*Table) GetTimeByColIndexMustGet

func (table *Table) GetTimeByColIndexMustGet(colIndex int, rowIndex int) (val time.Time)
Get time.Time table cell from colIndex at rowIndex

Like its non-MustGet alternative GetTimeByColIndex(), but panics on error, and does not return an error.

func (*Table) GetTimeMustGet

func (table *Table) GetTimeMustGet(colName string, rowIndex int) (val time.Time)

Get time.Time table cell from colName at rowIndex

Like its non-MustGet alternative GetTime(), but panics on error, and does not return an error.

func (*Table) GetUint

func (table *Table) GetUint(colName string, rowIndex int) (val uint, err error)

Get uint table cell from colName at rowIndex

func (*Table) GetUint16

func (table *Table) GetUint16(colName string, rowIndex int) (val uint16, err error)

Get uint16 table cell from colName at rowIndex

func (*Table) GetUint16ByColIndex

func (table *Table) GetUint16ByColIndex(colIndex int, rowIndex int) (val uint16, err error)

Get uint16 table cell from colIndex at rowIndex

func (*Table) GetUint16ByColIndexMustGet

func (table *Table) GetUint16ByColIndexMustGet(colIndex int, rowIndex int) (val uint16)
Get uint16 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetUint16ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetUint16MustGet

func (table *Table) GetUint16MustGet(colName string, rowIndex int) (val uint16)

Get uint16 table cell from colName at rowIndex

Like its non-MustGet alternative GetUint16(), but panics on error, and does not return an error.

func (*Table) GetUint32

func (table *Table) GetUint32(colName string, rowIndex int) (val uint32, err error)

Get uint32 table cell from colName at rowIndex

func (*Table) GetUint32ByColIndex

func (table *Table) GetUint32ByColIndex(colIndex int, rowIndex int) (val uint32, err error)

Get uint32 table cell from colIndex at rowIndex

func (*Table) GetUint32ByColIndexMustGet

func (table *Table) GetUint32ByColIndexMustGet(colIndex int, rowIndex int) (val uint32)
Get uint32 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetUint32ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetUint32MustGet

func (table *Table) GetUint32MustGet(colName string, rowIndex int) (val uint32)

Get uint32 table cell from colName at rowIndex

Like its non-MustGet alternative GetUint32(), but panics on error, and does not return an error.

func (*Table) GetUint64

func (table *Table) GetUint64(colName string, rowIndex int) (val uint64, err error)

Get uint64 table cell from colName at rowIndex

func (*Table) GetUint64ByColIndex

func (table *Table) GetUint64ByColIndex(colIndex int, rowIndex int) (val uint64, err error)

Get uint64 table cell from colIndex at rowIndex

func (*Table) GetUint64ByColIndexMustGet

func (table *Table) GetUint64ByColIndexMustGet(colIndex int, rowIndex int) (val uint64)
Get uint64 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetUint64ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetUint64MustGet

func (table *Table) GetUint64MustGet(colName string, rowIndex int) (val uint64)

Get uint64 table cell from colName at rowIndex

Like its non-MustGet alternative GetUint64(), but panics on error, and does not return an error.

func (*Table) GetUint8

func (table *Table) GetUint8(colName string, rowIndex int) (val uint8, err error)

Get uint8 table cell from colName at rowIndex

func (*Table) GetUint8ByColIndex

func (table *Table) GetUint8ByColIndex(colIndex int, rowIndex int) (val uint8, err error)

Get uint8 table cell from colIndex at rowIndex

func (*Table) GetUint8ByColIndexMustGet

func (table *Table) GetUint8ByColIndexMustGet(colIndex int, rowIndex int) (val uint8)
Get uint8 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetUint8ByColIndex(), but panics on error, and does not return an error.

func (*Table) GetUint8MustGet

func (table *Table) GetUint8MustGet(colName string, rowIndex int) (val uint8)

Get uint8 table cell from colName at rowIndex

Like its non-MustGet alternative GetUint8(), but panics on error, and does not return an error.

func (*Table) GetUint8Slice

func (table *Table) GetUint8Slice(colName string, rowIndex int) (val []uint8, err error)

Get []uint8 table cell from colName at rowIndex

func (*Table) GetUint8SliceByColIndex

func (table *Table) GetUint8SliceByColIndex(colIndex int, rowIndex int) (val []uint8, err error)

Get []uint8 table cell from colIndex at rowIndex

func (*Table) GetUint8SliceByColIndexMustGet

func (table *Table) GetUint8SliceByColIndexMustGet(colIndex int, rowIndex int) (val []uint8)
Get []uint8 table cell from colIndex at rowIndex

Like its non-MustGet alternative GetUint8SliceByColIndex(), but panics on error, and does not return an error.

func (*Table) GetUint8SliceMustGet

func (table *Table) GetUint8SliceMustGet(colName string, rowIndex int) (val []uint8)

Get []uint8 table cell from colName at rowIndex

Like its non-MustGet alternative GetUint8Slice(), but panics on error, and does not return an error.

func (*Table) GetUintByColIndex

func (table *Table) GetUintByColIndex(colIndex int, rowIndex int) (val uint, err error)

Get uint table cell from colIndex at rowIndex

func (*Table) GetUintByColIndexMustGet

func (table *Table) GetUintByColIndexMustGet(colIndex int, rowIndex int) (val uint)
Get uint table cell from colIndex at rowIndex

Like its non-MustGet alternative GetUintByColIndex(), but panics on error, and does not return an error.

func (*Table) GetUintMustGet

func (table *Table) GetUintMustGet(colName string, rowIndex int) (val uint)

Get uint table cell from colName at rowIndex

Like its non-MustGet alternative GetUint(), but panics on error, and does not return an error.

func (*Table) GetVal

func (table *Table) GetVal(colName string, rowIndex int) (interface{}, error)

Returns an interface{} value which may contain any valid gotables data type or NaN.

func (*Table) GetValAsString

func (table *Table) GetValAsString(colName string, rowIndex int) (string, error)

func (*Table) GetValAsStringByColIndex

func (table *Table) GetValAsStringByColIndex(colIndex int, rowIndex int) (string, error)

func (*Table) GetValByColIndex

func (table *Table) GetValByColIndex(colIndex int, rowIndex int) (interface{}, error)

Returns an interface{} value which may contain any valid gotables data type or NaN.

func (*Table) GetValByColIndexMustGet

func (table *Table) GetValByColIndexMustGet(colIndex int, rowIndex int) (val interface{})

Returns an interface{} value which may contain any valid gotables data type or NaN.

Like its non-MustGet alternative but panics on error.

func (*Table) GetValMustGet

func (table *Table) GetValMustGet(colName string, rowIndex int) (val interface{})

Returns an interface{} value which may contain any valid gotables data type or NaN.

Like its non-MustGet alternative but panics on error.

func (*Table) GobEncode

func (table *Table) GobEncode() ([]byte, error)

Note: GOB encoding and decoding does not (yet) support nested tables or type time.Time.

Example (Table)

GOB

s := `[sable_fur]
    i   s      f       t     b    bb            ui8
    int string float64 bool  byte []byte        []uint8
    1   "abc"  2.3     true  11   [11 12 13 14] [15 16 17]
    2   "xyz"  4.5     false 22   [22 23 24 25] [26 27 28]
    3   "ssss" 4.9     false 33   [33 34 35 36] [37 38 39]
    `
tableToBeEncoded, err := NewTableFromString(s)
if err != nil {
	fmt.Println(err)
}
fmt.Println("(1) Table ready to encode into binary.")
fmt.Println(tableToBeEncoded)

// Encode into binary.
var binary []byte
binary, err = tableToBeEncoded.GobEncode()
if err != nil {
	fmt.Println(err)
}

// Now decode it back from binary to type *gotables.Table
// Note: NewTableFromGob(binary) is equivalent to GobDecodeTable(binary)
tableDecoded, err := NewTableFromGob(binary)
if err != nil {
	fmt.Println(err)
}
fmt.Println("(2) Table decoded from binary.")
fmt.Println(tableDecoded)

equals, err := tableDecoded.Equals(tableToBeEncoded)
if err != nil {
	fmt.Println(err)
}
fmt.Printf("tableDecoded.Equals(tableToBeEncoded) = %t\n", equals)
Output:

(1) Table ready to encode into binary.
[sable_fur]
  i s            f t        b bb            ui8
int string float64 bool  byte []byte        []uint8
  1 "abc"      2.3 true    11 [11 12 13 14] [15 16 17]
  2 "xyz"      4.5 false   22 [22 23 24 25] [26 27 28]
  3 "ssss"     4.9 false   33 [33 34 35 36] [37 38 39]

(2) Table decoded from binary.
[sable_fur]
  i s            f t        b bb            ui8
int string float64 bool  byte []byte        []uint8
  1 "abc"      2.3 true    11 [11 12 13 14] [15 16 17]
  2 "xyz"      4.5 false   22 [22 23 24 25] [26 27 28]
  3 "ssss"     4.9 false   33 [33 34 35 36] [37 38 39]

tableDecoded.Equals(tableToBeEncoded) = true

func (*Table) HasCell

func (table *Table) HasCell(colName string, rowIndex int) (bool, error)

Returns true if this table has colName and has rowIndex.

func (*Table) HasCellByColIndex

func (table *Table) HasCellByColIndex(colIndex int, rowIndex int) (bool, error)

Returns true if this table has colIndex and has rowIndex.

func (*Table) HasCol

func (table *Table) HasCol(colName string) (bool, error)

Checks whether col exists

func (*Table) HasColByColIndex

func (table *Table) HasColByColIndex(colIndex int) (bool, error)

Checks whether col exists

func (*Table) HasRow

func (table *Table) HasRow(rowIndex int) (bool, error)

func (*Table) IsColType

func (table *Table) IsColType(colName string, typeNameQuestioning string) (bool, error)

func (*Table) IsColTypeByColIndex

func (table *Table) IsColTypeByColIndex(colIndex int, typeNameQuestioning string) (bool, error)

func (*Table) IsNilTable

func (table *Table) IsNilTable() (bool, error)

func (*Table) IsSortKey

func (table *Table) IsSortKey(colName string) (bool, error)

True if colName is a sort key in table. False if not. Error if colName not in table.

func (*Table) IsStructShape

func (table *Table) IsStructShape() (bool, error)

func (*Table) IsValidCellValue

func (table *Table) IsValidCellValue(colName string, value interface{}) (bool, error)

Test that this value is a valid type for this column.

Alias of IsValidColValue()

func (*Table) IsValidColValue

func (table *Table) IsValidColValue(colName string, value interface{}) (bool, error)

Test that this value is a valid type for this column.

Alias of IsValidCellValue()

func (*Table) IsValidRow

func (table *Table) IsValidRow(rowIndex int) (bool, error)

Check for missing values in this row. That means completely missing values, not just empty strings or NaN floats.

func (*Table) IsValidTable

func (table *Table) IsValidTable() (isValid bool, err error)

Test internal consistency of this table:

Valid table name?
Valid col names?
Valid col types?
Valid (equal) lengths of internal slices of col names, col types?
Valid data in each cell of each row?
Valid sort keys (if any are set)?

func (*Table) IsValidTableNesting

func (table *Table) IsValidTableNesting() (valid bool, err error)

Returns false if ANY table (including the top level table) exists more than once in the top level table or in any nested table. In other words: no duplicate tables whatsoever.

The purpose is to completely eliminate the possibility of circular references.

func (*Table) JoinColVals

func (table *Table) JoinColVals(colName string, separator string) (string, error)

Join together a column of values. To compose a set of commands into a single command.

Example
tableString :=
	`[commands]
	command
	string
	"echo myfile"
	"wc -l"
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

joined, err := table.JoinColVals("command", " | ")
if err != nil {
	log.Println(err)
}

fmt.Println(joined)
Output:

[commands]
command
string
"echo myfile"
"wc -l"

echo myfile | wc -l

func (*Table) JoinColValsByColIndex

func (table *Table) JoinColValsByColIndex(colIndex int, separator string) (string, error)

Join together a column of values. To compose a set of commands into a single command.

Example
tableString :=
	`[commands]
	command
	string
	"echo myfile"
	"wc -l"
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

colIndex := 0
joined, err := table.JoinColValsByColIndex(colIndex, " | ")
if err != nil {
	log.Println(err)
}

fmt.Println(joined)
Output:

[commands]
command
string
"echo myfile"
"wc -l"

echo myfile | wc -l

func (*Table) Merge

func (table1 *Table) Merge(table2 *Table) (merged *Table, err error)
	Merge table1 and table2 and return merged (table) of table1 and table2 columns and rows.

	table1 and table2 must share compatible sort key columns: same names and types.

	Sort keys for the key columns must be set in table1 (or table2): table1.SetSortKeys() and optionally table1.SetSortKeysReverse()

	For each matching row (or rows -- duplicates will be removed) in each table the non-key cells will be merged
	using the following rules:

        There are 4 possibilities (based on whether the cells have zero values -- soft-null):
        -----------------------------------------------------------------------------------------------
        Combination | table1.cell | table2.cell | Action              | Remarks
        -----------------------------------------------------------------------------------------------
        (a)         | zero       == zero        | do nothing
        (b)         | zero       <- non-zero    | copy cell2 to cell1 | Assumes zero is a missing value
        (c)         | non-zero   -> zero        | copy cell1 to cell2 | Assumes zero is a missing value
        (d)         | non-zero   -> non-zero    | copy cell1 to cell2 | (table1 takes precedence)

        There are 2 further possibilities with float32 and float64 (based on NaN values -- hard-null):
        -----------------------------------------------------------------------------------------------
        Combination | table1.cell | table2.cell | Action
        -----------------------------------------------------------------------------------------------
        (e)         | zero       -> NaN         | copy cell1 to cell2 | Assumes zero is NOT a missing value
        (f)         | NaN        <- zero        | copy cell2 to cell1 | Assumes zero is NOT a missing value
        -----------------------------------------------------------------------------------------------
Example
t1string :=
	`[Table1]
    XYZ     y   s       f       i   diff
    string  int string  float64 int int
    "X"     1   "abc"   1.11    1   7
    "Y"     3   "ghi"   7.8910  3   8
    "Z"     2   "def"   NaN     2   9
    "A"     4   "jkl"   0       4   6
    "B"     5   "mno"   0       5   4
    "C"     8   "pqr"   NaN     6   45
    `
table1, err := NewTableFromString(t1string)
if err != nil {
	log.Println(err)
}

fmt.Println(table1)

t2string :=
	`[Table2]
    s       b       diff    ui      f		i
    string  bool    int     uint    float64	int
    "abc"   true    55      99      2.22	1
    "def"   false   66      88      0		2
    "ghi"   false   66      0       42		3
    "jkl"   false   66      88      NaN		4
    "mno"   false   77      95      0		5
    "pqr"   true    88      97      0		6
    "pqr"   true    88      97      0		6
    `
table2, err := NewTableFromString(t2string)
if err != nil {
	log.Println(err)
}

fmt.Println(table2)

// These tables share sort keys i and s

// Note that there is a duplicate row,
// which will be removed during merging.

// At least one of the tables must have these sort keys set.

err = table1.SetSortKeys("i", "s")
if err != nil {
	log.Println(err)
}

merged, err := table1.Merge(table2)
if err != nil {
	log.Println(err)
}

fmt.Println(merged)
Output:

[Table1]
XYZ      y s            f   i diff
string int string float64 int  int
"X"      1 "abc"    1.11    1    7
"Y"      3 "ghi"    7.891   3    8
"Z"      2 "def"      NaN   2    9
"A"      4 "jkl"    0.0     4    6
"B"      5 "mno"    0.0     5    4
"C"      8 "pqr"      NaN   6   45

[Table2]
s      b     diff   ui       f   i
string bool   int uint float64 int
"abc"  true    55   99    2.22   1
"def"  false   66   88    0.0    2
"ghi"  false   66    0   42.0    3
"jkl"  false   66   88     NaN   4
"mno"  false   77   95    0.0    5
"pqr"  true    88   97    0.0    6
"pqr"  true    88   97    0.0    6

[Merged]
  i s      XYZ      y       f diff b       ui
int string string int float64  int bool  uint
  1 "abc"  "X"      1   1.11     7 true    99
  2 "def"  "Z"      2   0.0      9 false   88
  3 "ghi"  "Y"      3   7.891    8 false    0
  4 "jkl"  "A"      4   0.0      6 false   88
  5 "mno"  "B"      5   0.0      4 false   95
  6 "pqr"  "C"      8   0.0     45 true    97

func (*Table) Name

func (table *Table) Name() string

func (*Table) Nest

func (table *Table) Nest(nestable *Table, nestColName string) error

Split nestable by keys (which must match table) into separate tables.

Nest each separate table into the matching (by keys) cell in nestColName col in table.

Each nested table is given table name nestColName.

Each nested table is stored as a string. To retrieve it:

var nestedString string
var nestedTable *gotables.Table
nestedString, _ = table.GetString(nestColName, rowIndex)
nestedTable,  _ = gotables.NewTableFromString(nestedString)

func (*Table) NewTableFromRows

func (table *Table) NewTableFromRows(newTableName string, firstRow int, lastRow int) (*Table, error)

Create a new table from a range of rows in this table.

func (*Table) NewTableFromRowsBySearchRange

func (table *Table) NewTableFromRowsBySearchRange(newTableName string, searchValues ...interface{}) (*Table, error)

Create a new table from a range of rows in this table searched by keys.

func (*Table) NewTableReorderCols

func (table *Table) NewTableReorderCols(orderNames ...string) (reorderedTable *Table, err error)

Change the order of columns to the order provided by orderNames slice or arguments of col names.

A new table is created and returned.

Example
var err error
var table *Table
var tableString string = `
	[TypesGalore03]
    i   s      f       t     b    ui    bb            uu8
    int string float64 bool  byte uint8 []byte        []uint8
    1   "abc"  2.3     true  11   0     [11 12 13 14] [15 16 17]
    2   "xyz"  4.5     false 22   1     [22 23 24 25] [26 27 28]
    3   "ssss" 4.9     false 33   2     [33 34 35 36] [37 38 39]
    `
table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

// This method reorders the table cols in-place, and does not return a new table.

// Let's reorder the cols in alphabetic order.
colsOrder := []string{"i", "s", "f", "t", "b", "ui", "bb", "uu8"}
sort.Strings(colsOrder)
reorderedTable, err := table.NewTableReorderCols(colsOrder...)
if err != nil {
	log.Println(err)
}

fmt.Println(reorderedTable)
Output:

[TypesGalore03]
  i s            f t        b    ui bb            uu8
int string float64 bool  byte uint8 []byte        []uint8
  1 "abc"      2.3 true    11     0 [11 12 13 14] [15 16 17]
  2 "xyz"      4.5 false   22     1 [22 23 24 25] [26 27 28]
  3 "ssss"     4.9 false   33     2 [33 34 35 36] [37 38 39]

[TypesGalore03]
   b bb                  f   i s      t        ui uu8
byte []byte        float64 int string bool  uint8 []uint8
  11 [11 12 13 14]     2.3   1 "abc"  true      0 [15 16 17]
  22 [22 23 24 25]     4.5   2 "xyz"  false     1 [26 27 28]
  33 [33 34 35 36]     4.9   3 "ssss" false     2 [37 38 39]

func (*Table) NewTableReorderColsByColIndex

func (table *Table) NewTableReorderColsByColIndex(orderIndices ...int) (reorderedTable *Table, err error)

Change the order of columns to the order provided by orderIndices slice or arguments of col indices.

A new table is created and returned.

Example
var err error
var table *Table
var tableString string = `
	[TypesGalore01]
    i   s      f       t     b    ui    bb            uu8
    int string float64 bool  byte uint8 []byte        []uint8
    1   "abc"  2.3     true  11   0     [11 12 13 14] [15 16 17]
    2   "xyz"  4.5     false 22   1     [22 23 24 25] [26 27 28]
    3   "ssss" 4.9     false 33   2     [33 34 35 36] [37 38 39]
    `
table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

// This numeric sequence reverses the column order.
reorderedTable, err := table.NewTableReorderColsByColIndex(7, 6, 5, 4, 3, 2, 1, 0)
if err != nil {
	log.Println(err)
}

fmt.Println(reorderedTable)
Output:

[TypesGalore01]
  i s            f t        b    ui bb            uu8
int string float64 bool  byte uint8 []byte        []uint8
  1 "abc"      2.3 true    11     0 [11 12 13 14] [15 16 17]
  2 "xyz"      4.5 false   22     1 [22 23 24 25] [26 27 28]
  3 "ssss"     4.9 false   33     2 [33 34 35 36] [37 38 39]

[TypesGalore01]
uu8        bb               ui    b t           f s        i
[]uint8    []byte        uint8 byte bool  float64 string int
[15 16 17] [11 12 13 14]     0   11 true      2.3 "abc"    1
[26 27 28] [22 23 24 25]     1   22 false     4.5 "xyz"    2
[37 38 39] [33 34 35 36]     2   33 false     4.9 "ssss"   3

func (*Table) OrderColsBySortKeys

func (table *Table) OrderColsBySortKeys() error

Move sort key columns to the left of the table, and into sort key order.

Note: This is purely for human readability. It is not required for sorting.

Example
tableString :=
	`[MyTable]
	ColA   ColB Key2      ColC Key1 ColD ColE
	string  int string float64  int  int bool
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

err = table.SetSortKeys("Key1", "Key2")
if err != nil {
	log.Println(err)
}

fmt.Println("(1) Here is the table in its original column order:")
fmt.Println(table)

fmt.Println("(2) Here are the keys:")
sortKeysTable, err := table.GetSortKeysAsTable()
if err != nil {
	log.Println(err)
}
fmt.Println(sortKeysTable)

fmt.Println("(3) Order the sort key columns to the left:")
err = table.OrderColsBySortKeys()
if err != nil {
	log.Println(err)
}
fmt.Println(table)
Output:

(1) Here is the table in its original column order:
[MyTable]
ColA   ColB Key2      ColC Key1 ColD ColE
string  int string float64  int  int bool

(2) Here are the keys:
[SortKeys]
index colName colType  reverse
  int string  string   bool
    0 "Key1"  "int"    false
    1 "Key2"  "string" false

(3) Order the sort key columns to the left:
[MyTable]
Key1 Key2   ColA   ColB    ColC ColD ColE
 int string string  int float64  int bool

func (*Table) RenameCol

func (table *Table) RenameCol(oldName string, newName string) error

Note: This may leave the table in an invalid or unstable state if an error is returned.

func (*Table) RenameTable

func (table *Table) RenameTable(tableName string) error

Alias of SetName()

Note: If this table is inside a TableSet, be sure to not set the table name the same as another table in the TableSet. To avoid this, use the TableSet.RenameTable() method.

func (*Table) ReorderCols

func (table *Table) ReorderCols(orderNames ...string) (err error)

Change the order of columns to the order provided by orderNames slice or arguments of col names.

The table is reordered in-place.

Example
var err error
var table *Table
var tableString string = `
	[TypesGalore04]
    i   s      f       t     b    ui    bb            uu8
    int string float64 bool  byte uint8 []byte        []uint8
    1   "abc"  2.3     true  11   0     [11 12 13 14] [15 16 17]
    2   "xyz"  4.5     false 22   1     [22 23 24 25] [26 27 28]
    3   "ssss" 4.9     false 33   2     [33 34 35 36] [37 38 39]
    `
table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

// Let's reorder the cols in alphabetic order.
colsOrder := []string{"i", "s", "f", "t", "b", "ui", "bb", "uu8"}
sort.Strings(colsOrder)
// Let's reorder the cols in reverse order. Which here means reverse alphabetic order.
// Reversing algorithm from https://github.com/golang/go/wiki/SliceTricks
for left, right := 0, len(colsOrder)-1; left < right; left, right = left+1, right-1 {
	colsOrder[left], colsOrder[right] = colsOrder[right], colsOrder[left]
}
err = table.ReorderCols(colsOrder...)
if err != nil {
	log.Println(err)
}

fmt.Println(table)
Output:

[TypesGalore04]
  i s            f t        b    ui bb            uu8
int string float64 bool  byte uint8 []byte        []uint8
  1 "abc"      2.3 true    11     0 [11 12 13 14] [15 16 17]
  2 "xyz"      4.5 false   22     1 [22 23 24 25] [26 27 28]
  3 "ssss"     4.9 false   33     2 [33 34 35 36] [37 38 39]

[TypesGalore04]
uu8           ui t     s        i       f bb               b
[]uint8    uint8 bool  string int float64 []byte        byte
[15 16 17]     0 true  "abc"    1     2.3 [11 12 13 14]   11
[26 27 28]     1 false "xyz"    2     4.5 [22 23 24 25]   22
[37 38 39]     2 false "ssss"   3     4.9 [33 34 35 36]   33

func (*Table) ReorderColsByColIndex

func (table *Table) ReorderColsByColIndex(orderIndices ...int) error

Change the order of columns to the order provided by orderIndices slice or arguments of col indices.

The table is reordered in-place.

Example
var err error
var table *Table
var tableString string = `
	[TypesGalore02]
    i   s      f       t     b    ui    bb            uu8
    int string float64 bool  byte uint8 []byte        []uint8
    1   "abc"  2.3     true  11   0     [11 12 13 14] [15 16 17]
    2   "xyz"  4.5     false 22   1     [22 23 24 25] [26 27 28]
    3   "ssss" 4.9     false 33   2     [33 34 35 36] [37 38 39]
    `
table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

// This method reorders the table cols in-place, and does not return a new table.

// This numeric sequence reorders col names to alphabetic order.
err = table.ReorderColsByColIndex(4, 6, 2, 0, 1, 3, 5, 7)
if err != nil {
	log.Println(err)
}

fmt.Println(table)
Output:

[TypesGalore02]
   b bb                  f   i s      t        ui uu8
byte []byte        float64 int string bool  uint8 []uint8
  11 [11 12 13 14]     2.3   1 "abc"  true      0 [15 16 17]
  22 [22 23 24 25]     4.5   2 "xyz"  false     1 [26 27 28]
  33 [33 34 35 36]     4.9   3 "ssss" false     2 [37 38 39]

func (*Table) Reverse

func (table *Table) Reverse() error

Reverse the order of rows in this table.

func (*Table) RowCount

func (table *Table) RowCount() int

Return the number of rows in this table. Returns -1 if there is an error (namely: the table variable is nil).

func (*Table) Search

func (table *Table) Search(searchValues ...interface{}) (int, error)

Search this table by this table's currently-set sort keys.

To see the currently-set sort keys use GetSortKeysAsTable()

Note: This calls *Table.SearchFirst() which returns the first (if any) match in the table. Search first is what the Go sort.Search() function does.

Example (Keys1)
// mass:     Earth = 1 (relative to Earth)
// distance: Earth = 1 (relative to Earth - AU)
// http://www.windows2universe.org/our_solar_system/planets_table.html
// http://www.space.com/17001-how-big-is-the-sun-size-of-the-sun.html
tableString :=
	`[planets]
	name         mass distance moons index mnemonic
	string    float64   float64   int   int string
	"Sun"      333333        0     0    -1 ""
	"Mercury"   0.055      0.4     0     0 "my"
	"Venus"     0.815      0.7     0     1 "very"
	"Earth"     1.000      1.0     1     2 "elegant"
	"Mars"      0.107      1.5     2     3 "mother"
	"Jupiter" 318.000      5.2    79     4 "just"
	"Saturn"   95.000      9.5    82     5 "sat"
	"Uranus"   15.000     19.2    27     6 "upon"
	"Neptune"  17.000     30.6    13     7 "nine"
	"Pluto"     0.002     39.4     5     8 "porcupines"
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}
fmt.Println("(1) Unsorted table:")
fmt.Println(table)

// First let's sort the table by name.
err = table.SetSortKeys("name")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(2) Sorted table by name:")
fmt.Println(table)

searchValue := "Mars" // 2
fmt.Printf("(3) Search for name: %s\n", searchValue)
rowIndex, err := table.Search(searchValue)
if err != nil {
	log.Println(err)
}
fmt.Printf("Found %s at rowIndex = %d\n", searchValue, rowIndex)
fmt.Println()

searchValue = "Ceres" // -1
fmt.Printf("(4) Search for name: %s\n", searchValue)
rowIndex, _ = table.Search(searchValue)
fmt.Printf("Found %s at rowIndex = %d (missing)\n", searchValue, rowIndex)
Output:

(1) Unsorted table:
[planets]
name            mass distance moons index mnemonic
string       float64  float64   int   int string
"Sun"     333333.0        0.0     0    -1 ""
"Mercury"      0.055      0.4     0     0 "my"
"Venus"        0.815      0.7     0     1 "very"
"Earth"        1.0        1.0     1     2 "elegant"
"Mars"         0.107      1.5     2     3 "mother"
"Jupiter"    318.0        5.2    79     4 "just"
"Saturn"      95.0        9.5    82     5 "sat"
"Uranus"      15.0       19.2    27     6 "upon"
"Neptune"     17.0       30.6    13     7 "nine"
"Pluto"        0.002     39.4     5     8 "porcupines"

(2) Sorted table by name:
[planets]
name            mass distance moons index mnemonic
string       float64  float64   int   int string
"Earth"        1.0        1.0     1     2 "elegant"
"Jupiter"    318.0        5.2    79     4 "just"
"Mars"         0.107      1.5     2     3 "mother"
"Mercury"      0.055      0.4     0     0 "my"
"Neptune"     17.0       30.6    13     7 "nine"
"Pluto"        0.002     39.4     5     8 "porcupines"
"Saturn"      95.0        9.5    82     5 "sat"
"Sun"     333333.0        0.0     0    -1 ""
"Uranus"      15.0       19.2    27     6 "upon"
"Venus"        0.815      0.7     0     1 "very"

(3) Search for name: Mars
Found Mars at rowIndex = 2

(4) Search for name: Ceres
Found Ceres at rowIndex = -1 (missing)
Example (Keys1Reverse)
// mass:     Earth = 1 (relative to Earth)
// distance: Earth = 1 (relative to Earth - AU)
// http://www.windows2universe.org/our_solar_system/planets_table.html
tableString :=
	`[planets]
	name         mass distance moons index mnemonic
	string    float64  float64   int   int string
	"Mercury"   0.055      0.4     0     0 "my"
	"Venus"     0.815      0.7     0     1 "very"
	"Earth"     1.000      1.0     1     2 "elegant"
	"Mars"      0.107      1.5     2     3 "mother"
	"Jupiter" 318.000      5.2    79     4 "just"
	"Saturn"   95.000      9.5    82     5 "sat"
	"Uranus"   15.000     19.2    27     6 "upon"
	"Neptune"  17.000     30.6    13     7 "nine"
	"Pluto"     0.002     39.4     5     8 "porcupines"
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}
fmt.Println("(1) Unsorted table:")
fmt.Println(table)

// First let's sort the table by name in reverse.
err = table.SetSortKeys("name")
if err != nil {
	log.Println(err)
}
err = table.SetSortKeysReverse("name")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(2) Sorted table by name in reverse order:")
fmt.Println(table)

searchValue := "Mars" // 5
fmt.Printf("(3) Search for name: %s\n", searchValue)
rowIndex, err := table.Search(searchValue)
if err != nil {
	log.Println(err)
}
fmt.Printf("Found %s at rowIndex = %d\n", searchValue, rowIndex)

searchValue = "Ceres" // -1
fmt.Printf("(4) Search for name: %s\n", searchValue)
rowIndex, _ = table.Search(searchValue)
fmt.Printf("Found %s at rowIndex = %d (missing)\n", searchValue, rowIndex)
Output:

(1) Unsorted table:
[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Mercury"   0.055      0.4     0     0 "my"
"Venus"     0.815      0.7     0     1 "very"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Jupiter" 318.0        5.2    79     4 "just"
"Saturn"   95.0        9.5    82     5 "sat"
"Uranus"   15.0       19.2    27     6 "upon"
"Neptune"  17.0       30.6    13     7 "nine"
"Pluto"     0.002     39.4     5     8 "porcupines"

(2) Sorted table by name in reverse order:
[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Venus"     0.815      0.7     0     1 "very"
"Uranus"   15.0       19.2    27     6 "upon"
"Saturn"   95.0        9.5    82     5 "sat"
"Pluto"     0.002     39.4     5     8 "porcupines"
"Neptune"  17.0       30.6    13     7 "nine"
"Mercury"   0.055      0.4     0     0 "my"
"Mars"      0.107      1.5     2     3 "mother"
"Jupiter" 318.0        5.2    79     4 "just"
"Earth"     1.0        1.0     1     2 "elegant"

(3) Search for name: Mars
Found Mars at rowIndex = 6
(4) Search for name: Ceres
Found Ceres at rowIndex = -1 (missing)

func (*Table) SearchFirst

func (table *Table) SearchFirst(searchValues ...interface{}) (int, error)

Search this table by this table's currently-set sort keys.

To see the currently-set sort keys use GetSortKeysAsTable()

func (*Table) SearchLast

func (table *Table) SearchLast(searchValues ...interface{}) (int, error)

Search this table by this table's currently-set sort keys.

To see the currently-set sort keys use GetSortKeysAsTable()

Example
var data []int = []int{4, 8, 10, 10, 10, 20, 23, 29}
fmt.Printf("data: %v\n", data)
fmt.Println("index: 0 1  2  3  4  5  6  7")
fmt.Println()

fmt.Printf("(1) Find an element that is present:\n")
x := 23
fmt.Printf("Searching for x: %d\n", x)
i := SearchLast(len(data), func(i int) bool { return data[i] <= x })
fmt.Printf("x %d is, or would be, at index i: %d\n", x, i)

// Check whether x is actually where SearchLast() said it is, or would be inserted.
if i >= 0 && data[i] == x {
	fmt.Printf("x %d is present at data[%d]\n", x, i)
} else {
	fmt.Printf("x is not present in data, but i %d is the index where it would be inserted AFTER.\n", i)
	fmt.Printf("Note that i can be -1 which does not exist in data.\n")
}
fmt.Println()

fmt.Printf("(2) This time find an x that is present multiple times:\n")
x = 10
fmt.Printf("Searching for x: %d\n", x)
i = SearchLast(len(data), func(i int) bool { return data[i] <= x })
fmt.Printf("x %d is, or would be, at index i: %d\n", x, i)

// Check whether x is actually where SearchLast() said it is, or would be inserted.
if i >= 0 && data[i] == x {
	fmt.Printf("x %d is present at data[%d]\n", x, i)
} else {
	fmt.Printf("x is not present in data, but i %d is the index where it would be inserted AFTER.\n", i)
	fmt.Printf("Note that i can be -1 which does not exist in data.\n")
}
fmt.Println()

fmt.Printf("(3) This time find an x that is missing between items in data:\n")
x = 15
fmt.Printf("Searching for x: %d\n", x)
i = SearchLast(len(data), func(i int) bool { return data[i] <= x })
fmt.Printf("x %d is, or would be, at index i: %d\n", x, i)

// Check whether x is actually where SearchLast() said it is, or would be inserted.
if i >= 0 && data[i] == x {
	fmt.Printf("x %d is present at data[%d]\n", x, i)
} else {
	fmt.Printf("x is not present in data, but i %d is the index where it would be inserted AFTER.\n", i)
	fmt.Printf("Note that i can be -1 which does not exist in data.\n")
}
fmt.Println()

fmt.Printf("(4) This time find an x that is missing below all items in data:\n")
x = 3
fmt.Printf("Searching for x: %d\n", x)
i = SearchLast(len(data), func(i int) bool { return data[i] <= x })
fmt.Printf("x %d is, or would be, at index i: %d\n", x, i)

// Check whether x is actually where SearchLast() said it is, or would be inserted.
if i >= 0 && data[i] == x {
	fmt.Printf("x %d is present at data[%d]\n", x, i)
} else {
	fmt.Printf("x is not present in data, but i %d is the index where it would be inserted AFTER.\n", i)
	fmt.Printf("Note that i can be -1 which does not exist in data.\n")
}
fmt.Println()

fmt.Printf("(5) This time find an x that is missing above all items in data:\n")
x = 31
fmt.Printf("Searching for x: %d\n", x)
i = SearchLast(len(data), func(i int) bool { return data[i] <= x })
fmt.Printf("x %d is, or would be, at index i: %d\n", x, i)

// Check whether x is actually where SearchLast() said it is, or would be inserted.
if i >= 0 && data[i] == x {
	fmt.Printf("x %d is present at data[%d]\n", x, i)
} else {
	fmt.Printf("x is not present in data, but i %d is the index where it would be inserted AFTER.\n", i)
	fmt.Printf("Note that i can be -1 which does not exist in data.\n")
}
fmt.Println()
Output:

data: [4 8 10 10 10 20 23 29]
index: 0 1  2  3  4  5  6  7

(1) Find an element that is present:
Searching for x: 23
x 23 is, or would be, at index i: 6
x 23 is present at data[6]

(2) This time find an x that is present multiple times:
Searching for x: 10
x 10 is, or would be, at index i: 4
x 10 is present at data[4]

(3) This time find an x that is missing between items in data:
Searching for x: 15
x 15 is, or would be, at index i: 4
x is not present in data, but i 4 is the index where it would be inserted AFTER.
Note that i can be -1 which does not exist in data.

(4) This time find an x that is missing below all items in data:
Searching for x: 3
x 3 is, or would be, at index i: -1
x is not present in data, but i -1 is the index where it would be inserted AFTER.
Note that i can be -1 which does not exist in data.

(5) This time find an x that is missing above all items in data:
Searching for x: 31
x 31 is, or would be, at index i: 7
x is not present in data, but i 7 is the index where it would be inserted AFTER.
Note that i can be -1 which does not exist in data.

func (*Table) SearchRange

func (table *Table) SearchRange(searchValues ...interface{}) (firstRow int, lastRow int, err error)

Return the first and last index of 1 or more instances of searchValues in table.

Note: searchValues must match, not merely GT and LT where match would be.

func (*Table) SetAllFloatCellsToNaN

func (table *Table) SetAllFloatCellsToNaN() error

Set all float cells in this table to NaN. This is a convenience function to use NaN as a proxy for a missing value.

func (*Table) SetBool

func (table *Table) SetBool(colName string, rowIndex int, newVal bool) error

Set table cell in colName at rowIndex to newVal bool

func (*Table) SetBoolByColIndex

func (table *Table) SetBoolByColIndex(colIndex int, rowIndex int, newVal bool) error

Set table cell in colIndex at rowIndex to newVal bool

func (*Table) SetBoolByColIndexMustSet

func (table *Table) SetBoolByColIndexMustSet(colIndex int, rowIndex int, val bool)

Set bool MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetBoolByColIndex(), but panics on error, and does not return an error.

func (*Table) SetBoolMustSet

func (table *Table) SetBoolMustSet(colName string, rowIndex int, val bool)

Set bool MustSet table cell from colName

Like its non-MustSet alternative SetBool(), but panics on error, and does not return an error.

func (*Table) SetByte

func (table *Table) SetByte(colName string, rowIndex int, newVal byte) error

Set table cell in colName at rowIndex to newVal byte

func (*Table) SetByteByColIndex

func (table *Table) SetByteByColIndex(colIndex int, rowIndex int, newVal byte) error

Set table cell in colIndex at rowIndex to newVal byte

func (*Table) SetByteByColIndexMustSet

func (table *Table) SetByteByColIndexMustSet(colIndex int, rowIndex int, val byte)

Set byte MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetByteByColIndex(), but panics on error, and does not return an error.

func (*Table) SetByteMustSet

func (table *Table) SetByteMustSet(colName string, rowIndex int, val byte)

Set byte MustSet table cell from colName

Like its non-MustSet alternative SetByte(), but panics on error, and does not return an error.

func (*Table) SetByteSlice

func (table *Table) SetByteSlice(colName string, rowIndex int, newVal []byte) error

Set table cell in colName at rowIndex to newVal []byte

Example (Complete)
// Create a struct-shaped table with two cells
// for a string and a byte, just to show how it's done.
var s string = `[myTableStruct]
	hello string = "Hello world!"
	b byte = 255
	`

// Instantiate table from string.
table, err := NewTableFromString(s)
if err != nil {
	log.Println(err)
}
fmt.Println(table)

// Create a []byte (slice of byte) from another string.
hello := "Hello slice!"
var helloByteSlice []byte = make([]byte, len(hello))
for i, val := range hello {
	fmt.Printf("%s = byte %d\n", string(val), byte(val))
	helloByteSlice[i] = byte(val)
}
fmt.Printf("helloByteSlice = %v\n", helloByteSlice)

// Create a new column called helloSlice in the table.
err = table.AppendCol("helloSlice", "[]byte")
if err != nil {
	log.Println(err)
}

// Assign helloByteSlice to helloSlice cell at row 0
err = table.SetByteSlice("helloSlice", 0, helloByteSlice)
if err != nil {
	log.Println(err)
}
fmt.Printf("\n%s\n", table)

// Retrieve it.
var retrievedSlice []byte
retrievedSlice, err = table.GetByteSlice("helloSlice", 0)
if err != nil {
	log.Println(err)
}
fmt.Printf("retrievedSlice = %v\n", retrievedSlice)
Output:

[myTableStruct]
hello string = "Hello world!"
b byte = 255

H = byte 72
e = byte 101
l = byte 108
l = byte 108
o = byte 111
  = byte 32
s = byte 115
l = byte 108
i = byte 105
c = byte 99
e = byte 101
! = byte 33
helloByteSlice = [72 101 108 108 111 32 115 108 105 99 101 33]

[myTableStruct]
hello string = "Hello world!"
b byte = 255
helloSlice []byte = [72 101 108 108 111 32 115 108 105 99 101 33]

retrievedSlice = [72 101 108 108 111 32 115 108 105 99 101 33]

func (*Table) SetByteSliceByColIndex

func (table *Table) SetByteSliceByColIndex(colIndex int, rowIndex int, newVal []byte) error

Set table cell in colIndex at rowIndex to newVal []byte

func (*Table) SetByteSliceByColIndexMustSet

func (table *Table) SetByteSliceByColIndexMustSet(colIndex int, rowIndex int, val []byte)

Set []byte MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetByteSliceByColIndex(), but panics on error, and does not return an error.

func (*Table) SetByteSliceMustSet

func (table *Table) SetByteSliceMustSet(colName string, rowIndex int, val []byte)

Set []byte MustSet table cell from colName

Like its non-MustSet alternative SetByteSlice(), but panics on error, and does not return an error.

func (*Table) SetCellToZeroValue

func (table *Table) SetCellToZeroValue(colName string, rowIndex int) error
Example
s :=
	`[three_rows]
	i    s      f1      b     f2
	int  string float32 bool  float64
	0    "abc"  2.3     true  42.0
	1    "xyz"  4.5     false 43.0
	2    "s  s" 4.9     false 44.0
	`
table, err := NewTableFromString(s)
if err != nil {
	log.Println(err)
}

fmt.Println("Initial table:")
fmt.Println(table)

err = table.SetCellToZeroValue("s", 1)
if err != nil {
	log.Println(err)
}
fmt.Println("table.SetCellToZeroValue(\"s\", 1)")
fmt.Println(table)

err = table.SetCellToZeroValue("f1", 0)
if err != nil {
	log.Println(err)
}
fmt.Println("table.SetCellToZeroValue(\"f1\", 0)")
fmt.Println(table)

err = table.SetCellToZeroValue("b", 0)
if err != nil {
	log.Println(err)
}
fmt.Println("table.SetCellToZeroValue(\"b\", 0)")
fmt.Println(table)

err = table.SetCellToZeroValue("i", 2)
if err != nil {
	log.Println(err)
}
fmt.Println("table.SetCellToZeroValue(\"i\", 2)")
fmt.Println(table)
Output:

Initial table:
[three_rows]
  i s           f1 b          f2
int string float32 bool  float64
  0 "abc"      2.3 true       42
  1 "xyz"      4.5 false      43
  2 "s  s"     4.9 false      44

table.SetCellToZeroValue("s", 1)
[three_rows]
  i s           f1 b          f2
int string float32 bool  float64
  0 "abc"      2.3 true       42
  1 ""         4.5 false      43
  2 "s  s"     4.9 false      44

table.SetCellToZeroValue("f1", 0)
[three_rows]
  i s           f1 b          f2
int string float32 bool  float64
  0 "abc"      0.0 true       42
  1 ""         4.5 false      43
  2 "s  s"     4.9 false      44

table.SetCellToZeroValue("b", 0)
[three_rows]
  i s           f1 b          f2
int string float32 bool  float64
  0 "abc"      0.0 false      42
  1 ""         4.5 false      43
  2 "s  s"     4.9 false      44

table.SetCellToZeroValue("i", 2)
[three_rows]
  i s           f1 b          f2
int string float32 bool  float64
  0 "abc"      0.0 false      42
  1 ""         4.5 false      43
  0 "s  s"     4.9 false      44

func (*Table) SetCellToZeroValueByColIndex

func (table *Table) SetCellToZeroValueByColIndex(colIndex int, rowIndex int) error

func (*Table) SetColCellsToZeroValue

func (table *Table) SetColCellsToZeroValue(colName string) error

Set all cells in this col to their zero value, such as 0, "", or false.

func (*Table) SetColCellsToZeroValueByColIndex

func (table *Table) SetColCellsToZeroValueByColIndex(colIndex int) error

Set all cells in this col to their zero value, such as 0, "", or false.

func (*Table) SetFloat32

func (table *Table) SetFloat32(colName string, rowIndex int, newVal float32) error

Set table cell in colName at rowIndex to newVal float32

func (*Table) SetFloat32ByColIndex

func (table *Table) SetFloat32ByColIndex(colIndex int, rowIndex int, newVal float32) error

Set table cell in colIndex at rowIndex to newVal float32

func (*Table) SetFloat32ByColIndexMustSet

func (table *Table) SetFloat32ByColIndexMustSet(colIndex int, rowIndex int, val float32)

Set float32 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetFloat32ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetFloat32MustSet

func (table *Table) SetFloat32MustSet(colName string, rowIndex int, val float32)

Set float32 MustSet table cell from colName

Like its non-MustSet alternative SetFloat32(), but panics on error, and does not return an error.

func (*Table) SetFloat64

func (table *Table) SetFloat64(colName string, rowIndex int, newVal float64) error

Set table cell in colName at rowIndex to newVal float64

func (*Table) SetFloat64ByColIndex

func (table *Table) SetFloat64ByColIndex(colIndex int, rowIndex int, newVal float64) error

Set table cell in colIndex at rowIndex to newVal float64

func (*Table) SetFloat64ByColIndexMustSet

func (table *Table) SetFloat64ByColIndexMustSet(colIndex int, rowIndex int, val float64)

Set float64 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetFloat64ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetFloat64MustSet

func (table *Table) SetFloat64MustSet(colName string, rowIndex int, val float64)

Set float64 MustSet table cell from colName

Like its non-MustSet alternative SetFloat64(), but panics on error, and does not return an error.

func (*Table) SetInt

func (table *Table) SetInt(colName string, rowIndex int, newVal int) error

Set table cell in colName at rowIndex to newVal int

func (*Table) SetInt16

func (table *Table) SetInt16(colName string, rowIndex int, newVal int16) error

Set table cell in colName at rowIndex to newVal int16

func (*Table) SetInt16ByColIndex

func (table *Table) SetInt16ByColIndex(colIndex int, rowIndex int, newVal int16) error

Set table cell in colIndex at rowIndex to newVal int16

func (*Table) SetInt16ByColIndexMustSet

func (table *Table) SetInt16ByColIndexMustSet(colIndex int, rowIndex int, val int16)

Set int16 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetInt16ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetInt16MustSet

func (table *Table) SetInt16MustSet(colName string, rowIndex int, val int16)

Set int16 MustSet table cell from colName

Like its non-MustSet alternative SetInt16(), but panics on error, and does not return an error.

func (*Table) SetInt32

func (table *Table) SetInt32(colName string, rowIndex int, newVal int32) error

Set table cell in colName at rowIndex to newVal int32

func (*Table) SetInt32ByColIndex

func (table *Table) SetInt32ByColIndex(colIndex int, rowIndex int, newVal int32) error

Set table cell in colIndex at rowIndex to newVal int32

func (*Table) SetInt32ByColIndexMustSet

func (table *Table) SetInt32ByColIndexMustSet(colIndex int, rowIndex int, val int32)

Set int32 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetInt32ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetInt32MustSet

func (table *Table) SetInt32MustSet(colName string, rowIndex int, val int32)

Set int32 MustSet table cell from colName

Like its non-MustSet alternative SetInt32(), but panics on error, and does not return an error.

func (*Table) SetInt64

func (table *Table) SetInt64(colName string, rowIndex int, newVal int64) error

Set table cell in colName at rowIndex to newVal int64

func (*Table) SetInt64ByColIndex

func (table *Table) SetInt64ByColIndex(colIndex int, rowIndex int, newVal int64) error

Set table cell in colIndex at rowIndex to newVal int64

func (*Table) SetInt64ByColIndexMustSet

func (table *Table) SetInt64ByColIndexMustSet(colIndex int, rowIndex int, val int64)

Set int64 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetInt64ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetInt64MustSet

func (table *Table) SetInt64MustSet(colName string, rowIndex int, val int64)

Set int64 MustSet table cell from colName

Like its non-MustSet alternative SetInt64(), but panics on error, and does not return an error.

func (*Table) SetInt8

func (table *Table) SetInt8(colName string, rowIndex int, newVal int8) error

Set table cell in colName at rowIndex to newVal int8

func (*Table) SetInt8ByColIndex

func (table *Table) SetInt8ByColIndex(colIndex int, rowIndex int, newVal int8) error

Set table cell in colIndex at rowIndex to newVal int8

func (*Table) SetInt8ByColIndexMustSet

func (table *Table) SetInt8ByColIndexMustSet(colIndex int, rowIndex int, val int8)

Set int8 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetInt8ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetInt8MustSet

func (table *Table) SetInt8MustSet(colName string, rowIndex int, val int8)

Set int8 MustSet table cell from colName

Like its non-MustSet alternative SetInt8(), but panics on error, and does not return an error.

func (*Table) SetIntByColIndex

func (table *Table) SetIntByColIndex(colIndex int, rowIndex int, newVal int) error

Set table cell in colIndex at rowIndex to newVal int

func (*Table) SetIntByColIndexMustSet

func (table *Table) SetIntByColIndexMustSet(colIndex int, rowIndex int, val int)

Set int MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetIntByColIndex(), but panics on error, and does not return an error.

func (*Table) SetIntMustSet

func (table *Table) SetIntMustSet(colName string, rowIndex int, val int)

Set int MustSet table cell from colName

Like its non-MustSet alternative SetInt(), but panics on error, and does not return an error.

func (*Table) SetName

func (table *Table) SetName(tableName string) error

alias of RenameTable()

Note: If this table is inside a TableSet, be sure to not set the table name the same as another table in the TableSet. To avoid this, use the TableSet.SetName() method.

func (*Table) SetRowCellsToZeroValue

func (table *Table) SetRowCellsToZeroValue(rowIndex int) error

func (*Table) SetRowFloatCellsToNaN

func (table *Table) SetRowFloatCellsToNaN(rowIndex int) error

Set all float cells in this row to NaN. This is a convenience function to use NaN as a proxy for a missing value.

Example
s :=
	`[three_rows]
	i    s      f       b     f2
	int  string float32 bool  float64
	0    "abc"  2.3     true  42.0
	1    "xyz"  4.5     false 43.0
	2    "s  s" 4.9     false 44.0
	`
table, err := NewTableFromString(s)
if err != nil {
	log.Println(err)
}
fmt.Println("Before ...")
fmt.Println(table)

rowIndex := 1 // The middle row.
err = table.SetRowFloatCellsToNaN(rowIndex)
if err != nil {
	log.Println(err)
}

fmt.Println("After ...")
fmt.Println(table)
Output:

Before ...
[three_rows]
  i s            f b          f2
int string float32 bool  float64
  0 "abc"      2.3 true       42
  1 "xyz"      4.5 false      43
  2 "s  s"     4.9 false      44

After ...
[three_rows]
  i s            f b          f2
int string float32 bool  float64
  0 "abc"      2.3 true       42
  1 "xyz"      NaN false     NaN
  2 "s  s"     4.9 false      44

func (*Table) SetRune

func (table *Table) SetRune(colName string, rowIndex int, newVal rune) error

Set table cell in colName at rowIndex to newVal rune

func (*Table) SetRuneByColIndex

func (table *Table) SetRuneByColIndex(colIndex int, rowIndex int, newVal rune) error

Set table cell in colIndex at rowIndex to newVal rune

func (*Table) SetRuneByColIndexMustSet

func (table *Table) SetRuneByColIndexMustSet(colIndex int, rowIndex int, val rune)

Set rune MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetRuneByColIndex(), but panics on error, and does not return an error.

func (*Table) SetRuneMustSet

func (table *Table) SetRuneMustSet(colName string, rowIndex int, val rune)

Set rune MustSet table cell from colName

Like its non-MustSet alternative SetRune(), but panics on error, and does not return an error.

func (*Table) SetSortKeys

func (table *Table) SetSortKeys(sortColNames ...string) error

Call with an argument list, or a slice of string followed by an ellipsis ...

(1) Pass sort keys as separate arguments:

err = table.SetSortKeys("col1","col2","col3")

(2) Pass sort keys as a slice:

err = table.SetSortKeys([]string{"col1","col2","col3"}...)

(3) Pass sort keys as a slice:

sortColNames := []string{"col1","col2","col3"}
err = table.SetSortKeys(sortColNames...)

(4) Clear sort keys (if any) by calling with empty argument list:

err = table.SetSortKeys()
Example
tableString :=
	`[changes]
	user     language    lines
	string   string        int
	"gri"    "Go"          100
	"ken"    "C"           150
	"glenda" "Go"          200
	"rsc"    "Go"          200
	"r"      "Go"          100
	"ken"    "Go"          200
	"dmr"    "C"           100
	"r"      "C"           150
	"gri"    "Smalltalk"    80
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}
fmt.Println("(1) Unsorted table:")
fmt.Println(table)

// Sort the table by user.
if err = table.SetSortKeys("user"); err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(2) Sorted by user:")
fmt.Println(table)

// Sort by user and lines.
err = table.SetSortKeys("user", "lines")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(3) Sorted by user and lines:")
fmt.Println(table)

// Sort the table by user but reverse lines.
err = table.SetSortKeys("user", "lines")
if err != nil {
	log.Println(err)
}
err = table.SetSortKeysReverse("lines")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(4) Sort by user but reverse lines:")
fmt.Println(table)

// Sort the table by language and lines.
err = table.SetSortKeys("language", "lines")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(5) Sort by language and lines:")
fmt.Println(table)

// Sort the table by language and lines and user.
err = table.SetSortKeys("language", "lines", "user")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(6) Sort by language and lines and user:")
fmt.Println(table)

keysTable, err := table.GetSortKeysAsTable()
if err != nil {
	log.Println(err)
}
fmt.Println("(7) SortKeys as a table:")
fmt.Println(keysTable)
Output:

(1) Unsorted table:
[changes]
user     language    lines
string   string        int
"gri"    "Go"          100
"ken"    "C"           150
"glenda" "Go"          200
"rsc"    "Go"          200
"r"      "Go"          100
"ken"    "Go"          200
"dmr"    "C"           100
"r"      "C"           150
"gri"    "Smalltalk"    80

(2) Sorted by user:
[changes]
user     language    lines
string   string        int
"dmr"    "C"           100
"glenda" "Go"          200
"gri"    "Go"          100
"gri"    "Smalltalk"    80
"ken"    "C"           150
"ken"    "Go"          200
"r"      "Go"          100
"r"      "C"           150
"rsc"    "Go"          200

(3) Sorted by user and lines:
[changes]
user     language    lines
string   string        int
"dmr"    "C"           100
"glenda" "Go"          200
"gri"    "Smalltalk"    80
"gri"    "Go"          100
"ken"    "C"           150
"ken"    "Go"          200
"r"      "Go"          100
"r"      "C"           150
"rsc"    "Go"          200

(4) Sort by user but reverse lines:
[changes]
user     language    lines
string   string        int
"dmr"    "C"           100
"glenda" "Go"          200
"gri"    "Go"          100
"gri"    "Smalltalk"    80
"ken"    "Go"          200
"ken"    "C"           150
"r"      "C"           150
"r"      "Go"          100
"rsc"    "Go"          200

(5) Sort by language and lines:
[changes]
user     language    lines
string   string        int
"dmr"    "C"           100
"ken"    "C"           150
"r"      "C"           150
"r"      "Go"          100
"gri"    "Go"          100
"ken"    "Go"          200
"glenda" "Go"          200
"rsc"    "Go"          200
"gri"    "Smalltalk"    80

(6) Sort by language and lines and user:
[changes]
user     language    lines
string   string        int
"dmr"    "C"           100
"ken"    "C"           150
"r"      "C"           150
"gri"    "Go"          100
"r"      "Go"          100
"glenda" "Go"          200
"ken"    "Go"          200
"rsc"    "Go"          200
"gri"    "Smalltalk"    80

(7) SortKeys as a table:
[SortKeys]
index colName    colType  reverse
  int string     string   bool
    0 "language" "string" false
    1 "lines"    "int"    false
    2 "user"     "string" false

func (*Table) SetSortKeysFromTable

func (table *Table) SetSortKeysFromTable(fromTable *Table) error

Copy sort keys into table from fromTable.

func (*Table) SetSortKeysReverse

func (table *Table) SetSortKeysReverse(reverseSortColNames ...string) error

Call with an argument list, or a slice of string followed by ...

Example 1: SetSortKeysReverse("col1","col3")

Example 2: SetSortKeysReverse([]string{"col1","col3"}...)

func (*Table) SetString

func (table *Table) SetString(colName string, rowIndex int, newVal string) error

Set table cell in colName at rowIndex to newVal string

func (*Table) SetStringByColIndex

func (table *Table) SetStringByColIndex(colIndex int, rowIndex int, newVal string) error

Set table cell in colIndex at rowIndex to newVal string

func (*Table) SetStringByColIndexMustSet

func (table *Table) SetStringByColIndexMustSet(colIndex int, rowIndex int, val string)

Set string MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetStringByColIndex(), but panics on error, and does not return an error.

func (*Table) SetStringMustSet

func (table *Table) SetStringMustSet(colName string, rowIndex int, val string)

Set string MustSet table cell from colName

Like its non-MustSet alternative SetString(), but panics on error, and does not return an error.

func (*Table) SetStructShape

func (table *Table) SetStructShape(isStructShape bool) error

Will be ignored (when writing table as string) if table RowCount() is more than 1

func (*Table) SetTable

func (table *Table) SetTable(colName string, rowIndex int, newVal *Table) error

Set table cell in colName at rowIndex to newVal *Table

Example (CellTableSetToNilTableOrToNil)

Note: Leading lowercase in table is required for it to be recognised as an Example!

// A table literal. Sometimes easier than constructing a table programmatically.
tableString := `[MyTable]
		MyBool bool = true
		MyString string = "The answer to life, the universe and everything."
		MyInt int = 42
		myTable *Table = [CellTable]
		MyNilTable *Table = []
		`
table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

var nilReallyNilTable *Table = nil
err = table.SetTable("myTable", 0, nilReallyNilTable)
if err != nil {
	fmt.Println(err)
}
fmt.Println()

// Print the table with myTable cell set to nil.
// MyNilTable will have the !nil value of an empty and unnamed table.
fmt.Println(table)

// Print the individual cells.

// Here the table cell *Table is nil.

myTable, err := table.GetTable("myTable", 0)
if myTable == nil {
	fmt.Println("myTable == nil")
} else {
	fmt.Println("myTable != nil")
}
fmt.Printf("myTable: %v\n", myTable)

// Here the table cell *Table is set to a kind of nil *Table table (with no name) that's not actually <nil>.

MyNilTable, err := table.GetTable("MyNilTable", 0)
if MyNilTable == nil {
	fmt.Println("MyNilTable == nil")
} else {
	fmt.Println("MyNilTable != nil")
}
fmt.Printf("MyNilTable: %s", MyNilTable)
isValidTable, err := MyNilTable.IsValidTable()
fmt.Printf("MyNilTable.isValidTable() == %t\n", isValidTable)
fmt.Println(err)

// Now try to set a table cell to nil via several methods.

err = table.SetVal("myTable", 0, nil)
if err != nil {
	fmt.Println(err)
}

colIndex, _ := table.ColIndex("myTable")

err = table.SetValByColIndex(colIndex, 0, nil)
if err != nil {
	fmt.Println(err)
}

var nilTableVar *Table = nil

err = table.SetVal("myTable", 0, nilTableVar)
if err != nil {
	fmt.Println(err)
}

err = table.SetValByColIndex(colIndex, 0, nilTableVar)
if err != nil {
	fmt.Println(err)
}

err = table.SetTable("myTable", 0, nilTableVar)
if err != nil {
	fmt.Println(err)
}

err = table.SetTableByColIndex(colIndex, 0, nilTableVar)
if err != nil {
	fmt.Println(err)
}
Output:

[MyTable]
MyBool bool = true
MyString string = "The answer to life, the universe and everything."
MyInt int = 42
myTable *Table = [CellTable]
MyNilTable *Table = []

SetTable(myTable, 0, val): table [MyTable] col myTable expecting val of type *Table, not: <nil> [use NewNilTable() instead of <nil>]

[MyTable]
MyBool bool = true
MyString string = "The answer to life, the universe and everything."
MyInt int = 42
myTable *Table = [CellTable]
MyNilTable *Table = []

myTable != nil
myTable: [CellTable]

MyNilTable != nil
MyNilTable: []
MyNilTable.isValidTable() == false
ERROR IsValidTable(): table has no name
table.SetVal(myTable, 0, val=<nil>): val is <nil> [called by ExampleTable_SetTable_cellTableSetToNilTableOrToNil()]
table.SetValByColIndex(3, 0, val=<nil>): val is <nil> [caller: ExampleTable_SetTable_cellTableSetToNilTableOrToNil()]
table.SetVal(myTable, 0, val): val of type *Table is <nil> [called by ExampleTable_SetTable_cellTableSetToNilTableOrToNil()]
table.SetValByColIndex(3, 0, val): val of type *Table is <nil> [caller: ExampleTable_SetTable_cellTableSetToNilTableOrToNil()]
SetTable(myTable, 0, val): table [MyTable] col myTable expecting val of type *Table, not: <nil> [use NewNilTable() instead of <nil>]
SetTableByColIndex(3, 0, val): table [MyTable] col 3 expecting val of type *Table, not: <nil> [use NewNilTable() instead of <nil>]

func (*Table) SetTableByColIndex

func (table *Table) SetTableByColIndex(colIndex int, rowIndex int, newVal *Table) error

Set table cell in colIndex at rowIndex to newVal *Table

func (*Table) SetTableByColIndexMustSet

func (table *Table) SetTableByColIndexMustSet(colIndex int, rowIndex int, val *Table)

Set *Table MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetTableByColIndex(), but panics on error, and does not return an error.

func (*Table) SetTableMustSet

func (table *Table) SetTableMustSet(colName string, rowIndex int, val *Table)

Set *Table MustSet table cell from colName

Like its non-MustSet alternative SetTable(), but panics on error, and does not return an error.

func (*Table) SetTime

func (table *Table) SetTime(colName string, rowIndex int, newVal time.Time) error

Set table cell in colName at rowIndex to newVal time.Time

func (*Table) SetTimeByColIndex

func (table *Table) SetTimeByColIndex(colIndex int, rowIndex int, newVal time.Time) error

Set table cell in colIndex at rowIndex to newVal time.Time

func (*Table) SetTimeByColIndexMustSet

func (table *Table) SetTimeByColIndexMustSet(colIndex int, rowIndex int, val time.Time)

Set time.Time MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetTimeByColIndex(), but panics on error, and does not return an error.

func (*Table) SetTimeMustSet

func (table *Table) SetTimeMustSet(colName string, rowIndex int, val time.Time)

Set time.Time MustSet table cell from colName

Like its non-MustSet alternative SetTime(), but panics on error, and does not return an error.

func (*Table) SetUint

func (table *Table) SetUint(colName string, rowIndex int, newVal uint) error

Set table cell in colName at rowIndex to newVal uint

func (*Table) SetUint16

func (table *Table) SetUint16(colName string, rowIndex int, newVal uint16) error

Set table cell in colName at rowIndex to newVal uint16

func (*Table) SetUint16ByColIndex

func (table *Table) SetUint16ByColIndex(colIndex int, rowIndex int, newVal uint16) error

Set table cell in colIndex at rowIndex to newVal uint16

func (*Table) SetUint16ByColIndexMustSet

func (table *Table) SetUint16ByColIndexMustSet(colIndex int, rowIndex int, val uint16)

Set uint16 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetUint16ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetUint16MustSet

func (table *Table) SetUint16MustSet(colName string, rowIndex int, val uint16)

Set uint16 MustSet table cell from colName

Like its non-MustSet alternative SetUint16(), but panics on error, and does not return an error.

func (*Table) SetUint32

func (table *Table) SetUint32(colName string, rowIndex int, newVal uint32) error

Set table cell in colName at rowIndex to newVal uint32

func (*Table) SetUint32ByColIndex

func (table *Table) SetUint32ByColIndex(colIndex int, rowIndex int, newVal uint32) error

Set table cell in colIndex at rowIndex to newVal uint32

func (*Table) SetUint32ByColIndexMustSet

func (table *Table) SetUint32ByColIndexMustSet(colIndex int, rowIndex int, val uint32)

Set uint32 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetUint32ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetUint32MustSet

func (table *Table) SetUint32MustSet(colName string, rowIndex int, val uint32)

Set uint32 MustSet table cell from colName

Like its non-MustSet alternative SetUint32(), but panics on error, and does not return an error.

func (*Table) SetUint64

func (table *Table) SetUint64(colName string, rowIndex int, newVal uint64) error

Set table cell in colName at rowIndex to newVal uint64

func (*Table) SetUint64ByColIndex

func (table *Table) SetUint64ByColIndex(colIndex int, rowIndex int, newVal uint64) error

Set table cell in colIndex at rowIndex to newVal uint64

func (*Table) SetUint64ByColIndexMustSet

func (table *Table) SetUint64ByColIndexMustSet(colIndex int, rowIndex int, val uint64)

Set uint64 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetUint64ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetUint64MustSet

func (table *Table) SetUint64MustSet(colName string, rowIndex int, val uint64)

Set uint64 MustSet table cell from colName

Like its non-MustSet alternative SetUint64(), but panics on error, and does not return an error.

func (*Table) SetUint8

func (table *Table) SetUint8(colName string, rowIndex int, newVal uint8) error

Set table cell in colName at rowIndex to newVal uint8

func (*Table) SetUint8ByColIndex

func (table *Table) SetUint8ByColIndex(colIndex int, rowIndex int, newVal uint8) error

Set table cell in colIndex at rowIndex to newVal uint8

func (*Table) SetUint8ByColIndexMustSet

func (table *Table) SetUint8ByColIndexMustSet(colIndex int, rowIndex int, val uint8)

Set uint8 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetUint8ByColIndex(), but panics on error, and does not return an error.

func (*Table) SetUint8MustSet

func (table *Table) SetUint8MustSet(colName string, rowIndex int, val uint8)

Set uint8 MustSet table cell from colName

Like its non-MustSet alternative SetUint8(), but panics on error, and does not return an error.

func (*Table) SetUint8Slice

func (table *Table) SetUint8Slice(colName string, rowIndex int, newVal []uint8) error

Set table cell in colName at rowIndex to newVal []uint8

func (*Table) SetUint8SliceByColIndex

func (table *Table) SetUint8SliceByColIndex(colIndex int, rowIndex int, newVal []uint8) error

Set table cell in colIndex at rowIndex to newVal []uint8

func (*Table) SetUint8SliceByColIndexMustSet

func (table *Table) SetUint8SliceByColIndexMustSet(colIndex int, rowIndex int, val []uint8)

Set []uint8 MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetUint8SliceByColIndex(), but panics on error, and does not return an error.

func (*Table) SetUint8SliceMustSet

func (table *Table) SetUint8SliceMustSet(colName string, rowIndex int, val []uint8)

Set []uint8 MustSet table cell from colName

Like its non-MustSet alternative SetUint8Slice(), but panics on error, and does not return an error.

func (*Table) SetUintByColIndex

func (table *Table) SetUintByColIndex(colIndex int, rowIndex int, newVal uint) error

Set table cell in colIndex at rowIndex to newVal uint

func (*Table) SetUintByColIndexMustSet

func (table *Table) SetUintByColIndexMustSet(colIndex int, rowIndex int, val uint)

Set uint MustSet table cell from colName at rowIndex

Like its non-MustSet alternative SetUintByColIndex(), but panics on error, and does not return an error.

func (*Table) SetUintMustSet

func (table *Table) SetUintMustSet(colName string, rowIndex int, val uint)

Set uint MustSet table cell from colName

Like its non-MustSet alternative SetUint(), but panics on error, and does not return an error.

func (*Table) SetVal

func (table *Table) SetVal(colName string, rowIndex int, val interface{}) error

Requires a val of valid type for the col in the table.

func (*Table) SetValByColIndex

func (table *Table) SetValByColIndex(colIndex int, rowIndex int, val interface{}) error

Requires a val of valid type for the col in the table.

func (*Table) ShuffleDeterministic

func (table *Table) ShuffleDeterministic() error

Shuffle the rows in this table "deterministically", meaning the same size table will have its rows shuffled into the same shuffled order each time. That's why this function has an Example, because it has repeatable output.

Example
var err error
var table *Table

var tableString string = `[planets]
	name            mass distance moons index mnemonic
	string       float64  float64   int   int string
	"Sun"     333333.0        0.0     0     0 ""
	"Mercury"      0.055      0.4     0     1 "my"
	"Venus"        0.815      0.7     0     2 "very"
	"Earth"        1.0        1.0     1     3 "elegant"
	"Mars"         0.107      1.5     2     4 "mother"
	"Jupiter"    318.0        5.2    79     5 "just"
	"Saturn"      95.0        9.5    82     6 "sat"
	"Uranus"      15.0       19.2    27     7 "upon"
	"Neptune"     17.0       30.6    13     8 "nine"
	"Pluto"        0.002     39.4     5     9 "porcupines"
	`

table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

err = table.ShuffleDeterministic()
if err != nil {
	log.Println(err)
}

fmt.Println(table)
Output:

[planets]
name            mass distance moons index mnemonic
string       float64  float64   int   int string
"Sun"     333333.0        0.0     0     0 ""
"Mercury"      0.055      0.4     0     1 "my"
"Venus"        0.815      0.7     0     2 "very"
"Earth"        1.0        1.0     1     3 "elegant"
"Mars"         0.107      1.5     2     4 "mother"
"Jupiter"    318.0        5.2    79     5 "just"
"Saturn"      95.0        9.5    82     6 "sat"
"Uranus"      15.0       19.2    27     7 "upon"
"Neptune"     17.0       30.6    13     8 "nine"
"Pluto"        0.002     39.4     5     9 "porcupines"

[planets]
name            mass distance moons index mnemonic
string       float64  float64   int   int string
"Earth"        1.0        1.0     1     3 "elegant"
"Uranus"      15.0       19.2    27     7 "upon"
"Mars"         0.107      1.5     2     4 "mother"
"Saturn"      95.0        9.5    82     6 "sat"
"Mercury"      0.055      0.4     0     1 "my"
"Neptune"     17.0       30.6    13     8 "nine"
"Sun"     333333.0        0.0     0     0 ""
"Jupiter"    318.0        5.2    79     5 "just"
"Venus"        0.815      0.7     0     2 "very"
"Pluto"        0.002     39.4     5     9 "porcupines"

func (*Table) ShuffleRandom

func (table *Table) ShuffleRandom() error

Shuffle the rows in this table "randomly", meaning you will be unable to predict the resulting shuffled order. Non-deterministic.

Example
var err error
var table *Table

var tableString string = `[planets]
	name            mass distance moons index mnemonic
	string       float64  float64   int   int string
	"Sun"     333333.0        0.0     0     0 ""
	"Mercury"      0.055      0.4     0     1 "my"
	"Venus"        0.815      0.7     0     2 "very"
	"Earth"        1.0        1.0     1     3 "elegant"
	"Mars"         0.107      1.5     2     4 "mother"
	"Jupiter"    318.0        5.2    79     5 "just"
	"Saturn"      95.0        9.5    82     6 "sat"
	"Uranus"      15.0       19.2    27     7 "upon"
	"Neptune"     17.0       30.6    13     8 "nine"
	"Pluto"        0.002     39.4     5     9 "porcupines"
	`

table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

err = table.ShuffleRandom()
if err != nil {
	log.Println(err)
}

fmt.Println("ShuffleRandom() is \"truly\" random, so no predictable output.")
Output:

[planets]
name            mass distance moons index mnemonic
string       float64  float64   int   int string
"Sun"     333333.0        0.0     0     0 ""
"Mercury"      0.055      0.4     0     1 "my"
"Venus"        0.815      0.7     0     2 "very"
"Earth"        1.0        1.0     1     3 "elegant"
"Mars"         0.107      1.5     2     4 "mother"
"Jupiter"    318.0        5.2    79     5 "just"
"Saturn"      95.0        9.5    82     6 "sat"
"Uranus"      15.0       19.2    27     7 "upon"
"Neptune"     17.0       30.6    13     8 "nine"
"Pluto"        0.002     39.4     5     9 "porcupines"

ShuffleRandom() is "truly" random, so no predictable output.

func (*Table) Sort

func (table *Table) Sort(sortCols ...string) error

table.Sort() has 2 modes:-

Mode (1) With args: Sort this table by 1 or more column names provided as arguments, OR

Mode (2) Zero args: Sort this table by this table's currently-set sort keys.

Mode (1) limitation: sorts in ascending order only.

To sort one or more columns (keys) in reverse-order ("key2" in this example):

table.SetSortKeys("key1", "key2", "key3")
table.SetSortKeysReverse("key2")
table.Sort()

To see the currently-set sort keys use table.GetSortKeysAsTable()

Example
tableString :=
	`[planets]
	name         mass distance
	string    float64  float64
	"Mercury"   0.055      0.4
	"Venus"     0.815      0.7
	"Earth"     1.000      1.0
	"Mars"      0.107      1.5
	`

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}
fmt.Println("(1) Unsorted table:")
fmt.Println(table)

// First let's sort the table by name.
err = table.SetSortKeys("name")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(2) Sorted table by name:")
fmt.Println(table)

// Now let's sort the table by name but this time in reverse.
err = table.SetSortKeys("name")
if err != nil {
	log.Println(err)
}
err = table.SetSortKeysReverse("name")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}
fmt.Println("(3) Sorted table by name in reverse:")
fmt.Println(table)
Output:

(1) Unsorted table:
[planets]
name         mass distance
string    float64  float64
"Mercury"   0.055      0.4
"Venus"     0.815      0.7
"Earth"     1.0        1.0
"Mars"      0.107      1.5

(2) Sorted table by name:
[planets]
name         mass distance
string    float64  float64
"Earth"     1.0        1.0
"Mars"      0.107      1.5
"Mercury"   0.055      0.4
"Venus"     0.815      0.7

(3) Sorted table by name in reverse:
[planets]
name         mass distance
string    float64  float64
"Venus"     0.815      0.7
"Mercury"   0.055      0.4
"Mars"      0.107      1.5
"Earth"     1.0        1.0
Example (Complete)
tableString :=
	`[planets]
	name         mass distance moons index mnemonic
	string    float64  float64   int   int string
	"Mercury"   0.055      0.4     0     0 "my"
	"Venus"     0.815      0.7     0     1 "very"
	"Earth"     1.000      1.0     1     2 "elegant"
	"Mars"      0.107      1.5     2     3 "mother"
	"Jupiter" 318.000      5.2    79     4 "just"
	"Saturn"   95.000     29.4    82     5 "sat"
	"Uranus"   15.000     84.0    27     6 "upon"
	"Neptune"  17.000    164.0    13     7 "nine ... porcupines"
	`

var err error

table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}
fmt.Println(table)

var rowIndex int

// Get the name and mass of the first planet.
rowIndex = 0
fmt.Printf("rowIndex = %d\n", rowIndex)
name, err := table.GetString("name", rowIndex)
if err != nil {
	log.Println(err)
}
fmt.Printf("name = %s\n", name)

mass, err := table.GetFloat64("mass", rowIndex)
if err != nil {
	log.Println(err)
}
fmt.Printf("mass = %f\n", mass)
fmt.Println()

// Get and Set the mnemonic of the second planet.
rowIndex = 1
name, err = table.GetString("name", rowIndex)
if err != nil {
	log.Println(err)
}
fmt.Printf("name = %s\n", name)

mnemonic, err := table.GetString("mnemonic", rowIndex)
if err != nil {
	log.Println(err)
}
fmt.Printf("mnemonic = %s\n", mnemonic)

err = table.SetString("mnemonic", rowIndex, "VERY")
if err != nil {
	log.Println(err)
}

mnemonic, err = table.GetString("mnemonic", rowIndex)
if err != nil {
	log.Println(err)
}
fmt.Printf("mnemonic = %s\n", mnemonic)
fmt.Println()

// Sort and Search.
err = table.SetSortKeys("name")
if err != nil {
	log.Println(err)
}
err = table.Sort()
if err != nil {
	log.Println(err)
}

planet := "Mars"
rowIndex, err = table.Search(planet)
if err != nil {
	log.Println(err)
}

moons, err := table.GetInt("moons", rowIndex)
if err != nil {
	log.Println(err)
}

fmt.Println(table)
fmt.Printf("%s has %d moons.\n", planet, moons)
fmt.Println()

// Sort and Search Range.
err = table.SetSortKeys("moons")
if err != nil {
	log.Println(err)
}

err = table.Sort()
if err != nil {
	log.Println(err)
}

moons = 0
firstRowIndex, lastRowIndex, err := table.SearchRange(moons)
if err != nil {
	log.Println(err)
}

planets := lastRowIndex - firstRowIndex + 1
fmt.Println(table)
fmt.Printf("%d planets have %d moons.\n", planets, moons)
fmt.Println()

// Sort Unique.

tableString =
	`[Unique]
	KeyCol number   s
	int float32 string
	2   0       "two point two"
	2   2.2     ""
	1   1.1     "one point one"
	3   3.3     "three point three"
	3   3.3     ""
	3   NaN     "three point three"
	4   0.0     "neither zero nor same X"
	4   NaN     "neither zero nor same Y"
	4   4.4     "neither zero nor same Z"
	4   NaN     "neither zero nor same A"
	5   NaN     "minus 5"
	5   -0      "minus 5"
	5   -5      "minus 5"
	`
table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(table)

err = table.SetSortKeys("KeyCol")
if err != nil {
	log.Println(err)
}

tableUnique, err := table.SortUnique()
if err != nil {
	log.Println(err)
}
fmt.Println(tableUnique)
Output:

[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Mercury"   0.055      0.4     0     0 "my"
"Venus"     0.815      0.7     0     1 "very"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Jupiter" 318.0        5.2    79     4 "just"
"Saturn"   95.0       29.4    82     5 "sat"
"Uranus"   15.0       84.0    27     6 "upon"
"Neptune"  17.0      164.0    13     7 "nine ... porcupines"

rowIndex = 0
name = Mercury
mass = 0.055000

name = Venus
mnemonic = very
mnemonic = VERY

[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Earth"     1.0        1.0     1     2 "elegant"
"Jupiter" 318.0        5.2    79     4 "just"
"Mars"      0.107      1.5     2     3 "mother"
"Mercury"   0.055      0.4     0     0 "my"
"Neptune"  17.0      164.0    13     7 "nine ... porcupines"
"Saturn"   95.0       29.4    82     5 "sat"
"Uranus"   15.0       84.0    27     6 "upon"
"Venus"     0.815      0.7     0     1 "VERY"

Mars has 2 moons.

[planets]
name         mass distance moons index mnemonic
string    float64  float64   int   int string
"Venus"     0.815      0.7     0     1 "VERY"
"Mercury"   0.055      0.4     0     0 "my"
"Earth"     1.0        1.0     1     2 "elegant"
"Mars"      0.107      1.5     2     3 "mother"
"Neptune"  17.0      164.0    13     7 "nine ... porcupines"
"Uranus"   15.0       84.0    27     6 "upon"
"Jupiter" 318.0        5.2    79     4 "just"
"Saturn"   95.0       29.4    82     5 "sat"

2 planets have 0 moons.

[Unique]
KeyCol  number s
   int float32 string
     2     0.0 "two point two"
     2     2.2 ""
     1     1.1 "one point one"
     3     3.3 "three point three"
     3     3.3 ""
     3     NaN "three point three"
     4     0.0 "neither zero nor same X"
     4     NaN "neither zero nor same Y"
     4     4.4 "neither zero nor same Z"
     4     NaN "neither zero nor same A"
     5     NaN "minus 5"
     5    -0.0 "minus 5"
     5    -5.0 "minus 5"

[Unique]
KeyCol  number s
   int float32 string
     1     1.1 "one point one"
     2     2.2 "two point two"
     3     3.3 "three point three"
     4     4.4 "neither zero nor same A"
     5    -5.0 "minus 5"

func (*Table) SortKeyCount

func (table *Table) SortKeyCount() int

func (*Table) SortSimple

func (table *Table) SortSimple(sortCols ...string) error

Note: table.SortSimple() is now redundant, because table.Sort() now accepts sort col arguments.

Sort by one or more columns ascending-only.

1. All column keys are set to ascending order.

2. One or more column keys must be provided.

3. To sort one or more columns in reverse (eg with "key2" reversed):

table.SetSortKeys("key1", "key2", "key3")

table.SetSortKeysReverse("key2")

table.Sort()

4. SortSimple() sets the table's sort keys, so subsequent calls to table.Sort() will have the same effect as calling table.SetSortKeys() and then table.Sort()

Example
var tableString string
var table *Table
var err error

tableString =
	`[planets]
	name         mass distance moons index mnemonic
	string    float64   float64   int   int string
	"Earth"     1.000      1.0     1     2 "elegant"
	"Jupiter" 318.000      5.2    79     4 "just"
	"Mars"      0.107      1.5     2     3 "mother"
	"Mercury"   0.055      0.4     0     0 "my"
	"Neptune"  17.000     30.6    13     7 "nine"
	"Pluto"     0.002     39.4     5     8 "porcupines"
	"Saturn"   95.000      9.5    82     5 "sat"
	"Sun"      333333        0     0    -1 ""
	"Uranus"   15.000     19.2    27     6 "upon"
	"Venus"     0.815      0.7     0     1 "very"
	`

table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

// Single column sort. Sort the planets in order from the Sun.
err = table.SortSimple("distance")
if err != nil {
	log.Println(err)
}

fmt.Println(table)

tableString =
	`[changes]
	user     language    lines
	string   string        int
	"gri"    "Go"          100
	"ken"    "C"           150
	"glenda" "Go"          200
	"rsc"    "Go"          200
	"r"      "Go"          100
	"ken"    "Go"          200
	"dmr"    "C"           100
	"r"      "C"           150
	"gri"    "Smalltalk"    80
	`

table, err = NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

// Multiple column sort. Sort users by lines, language and user name.
err = table.SortSimple("lines", "language", "user")
if err != nil {
	log.Println(err)
}

fmt.Println(table)
Output:

[planets]
name            mass distance moons index mnemonic
string       float64  float64   int   int string
"Sun"     333333.0        0.0     0    -1 ""
"Mercury"      0.055      0.4     0     0 "my"
"Venus"        0.815      0.7     0     1 "very"
"Earth"        1.0        1.0     1     2 "elegant"
"Mars"         0.107      1.5     2     3 "mother"
"Jupiter"    318.0        5.2    79     4 "just"
"Saturn"      95.0        9.5    82     5 "sat"
"Uranus"      15.0       19.2    27     6 "upon"
"Neptune"     17.0       30.6    13     7 "nine"
"Pluto"        0.002     39.4     5     8 "porcupines"

[changes]
user     language    lines
string   string        int
"gri"    "Smalltalk"    80
"dmr"    "C"           100
"gri"    "Go"          100
"r"      "Go"          100
"ken"    "C"           150
"r"      "C"           150
"glenda" "Go"          200
"ken"    "Go"          200
"rsc"    "Go"          200

func (*Table) SortUnique

func (inputTable *Table) SortUnique(sortCols ...string) (newTableUnique *Table, err error)

Sort this table unique by this table's currently-set sort keys.

Non-key column cell values are not used for uniqueness but are evaluated and merged. Zero-value non-key cells will be replaced by available non-zero-value cells which match the same (possibly composite) key. If more than one non-zero-value cell is matches a key, any of those non-zero-values may be used, and is non-deterministic and no more stable than Go sort() which is not guaranteed to be stable.

table.SortUnique() has 2 modes:-

Mode (1) With args: Sort this table by 1 or more column names provided as arguments, OR

Mode (2) Zero args: Sort this table by this table's currently-set sort keys.

Mode (1) limitation: sorts in ascending order only.

To sort one or more columns (keys) in reverse-order ("key2" in this example):

table.SetSortKeys("key1", "key2", "key3")
table.SetSortKeysReverse("key2")
table.SortUnique()

To see the currently-set sort keys use table.GetSortKeysAsTable()

Note: The table is not sorted in-place. The returned table is new.

Note: SortUnique() uses table.Merge() which resolves missing or conflicting cell values.

Example
tableString :=
	`[Uniqueness]
	KeyCol number   s
	int float32 string
	2   0       "two point two"
	2   2.2     ""
	1   1.1     "one point one"
	3   3.3     "three point three"
	3   3.3     ""
	3   NaN     "three point three"
	4   0.0     "neither zero nor same X"
	4   NaN     "neither zero nor same Y"
	4   4.4     "neither zero nor same Z"
	4   NaN     "neither zero nor same A"
	5   NaN     "minus 5"
	5   -0      "minus 5"
	5   -5      "minus 5"
	`
table, err := NewTableFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println("Before SortUnique() ...")
fmt.Println(table)

err = table.SetSortKeys("KeyCol")
if err != nil {
	log.Println(err)
}

tableUnique, err := table.SortUnique()
if err != nil {
	log.Println(err)
}

fmt.Println("After SortUnique() ...")
fmt.Println(tableUnique)
Output:

Before SortUnique() ...
[Uniqueness]
KeyCol  number s
   int float32 string
     2     0.0 "two point two"
     2     2.2 ""
     1     1.1 "one point one"
     3     3.3 "three point three"
     3     3.3 ""
     3     NaN "three point three"
     4     0.0 "neither zero nor same X"
     4     NaN "neither zero nor same Y"
     4     4.4 "neither zero nor same Z"
     4     NaN "neither zero nor same A"
     5     NaN "minus 5"
     5    -0.0 "minus 5"
     5    -5.0 "minus 5"

After SortUnique() ...
[Uniqueness]
KeyCol  number s
   int float32 string
     1     1.1 "one point one"
     2     2.2 "two point two"
     3     3.3 "three point three"
     4     4.4 "neither zero nor same A"
     5    -5.0 "minus 5"

func (*Table) String

func (table *Table) String() string

Return a parsable table as a string with numbers format aligned right.

func (*Table) StringPadded

func (table *Table) StringPadded() string

func (*Table) StringUnpadded

func (table *Table) StringUnpadded() string
Example
// Deliberately padded (by hand) for contrast.
s :=
	`[sable_fur]
	  i s            f b          ff
	int string float32 bool  float64
	  1 "abc"     2.34 true    7.899
	  2 "xyz"     4.5  false   6
	  3 "s  s"    4.9  false   5.5
	`
table, err := NewTableFromString(s)
if err != nil {
	log.Println(err)
}

// Note: the default String() output for both TableSet and Table objects
// is padded into easy to read columns, with numeric columns aligned right.
// The design is: readability trumps compactness.
// There are alternatives where size matters, such as compression, and StringUnpadded()

// This is an example of StringUnpadded() which uses minimal spacing between values.

fmt.Println("TableSet (and Table) StringUnpadded() output:")
fmt.Println(table.StringUnpadded())
Output:

TableSet (and Table) StringUnpadded() output:
[sable_fur]
i s f b ff
int string float32 bool float64
1 "abc" 2.34 true 7.899
2 "xyz" 4.5 false 6
3 "s  s" 4.9 false 5.5

func (*Table) SwapCols

func (table *Table) SwapCols(colName1 string, colName2 string) error

Swap these two columns with each other.

func (*Table) SwapColsByColIndex

func (table *Table) SwapColsByColIndex(colIndex1 int, colIndex2 int) error

Swap these two columns with each other.

func (*Table) WriteFile

func (table *Table) WriteFile(fileName string, mode os.FileMode) error

Write a Table to a text file.

type TableExported

type TableExported struct {
	TableName   string
	ColNames    []string
	ColTypes    []string
	ColNamesMap map[string]int // To look up a colNames index from a col name.
	Rows        []tableRow
	SortKeys    []SortKeyExported
	StructShape bool
	IsNilTable  bool
	ParentTable *TableExported
}

For GOB.

type TableSet

type TableSet struct {
	// contains filtered or unexported fields
}

TableSet is an ordered set of *Table pointers.

func GobDecodeTableSet

func GobDecodeTableSet(buffer []bytes.Buffer) (*TableSet, error)

Reconstruct a TableSet from a slice of []bytes.Buffer

Each element in the slice is a Gob encoded table as a slice of []byte

Equivalent to NewTableSetFromGob()

Note: GOB encoding and decoding does not (yet) support nested tables or type time.Time.

func NewTableSet

func NewTableSet(tableSetName string) (*TableSet, error)

Factory function to return an initialised *TableSet pointer.

Example
tableSetName := "MyTableSet"
tableSet, err := NewTableSet(tableSetName)
if err != nil {
	log.Println(err)
}
tableCount := tableSet.TableCount()
name := tableSet.Name()
fmt.Println(tableCount)
fmt.Println(name)
fmt.Println()
fmt.Println(tableSet)
Output:

0
MyTableSet

[[MyTableSet]]

func NewTableSetFromFile

func NewTableSetFromFile(fileName string) (*TableSet, error)

Read and parse a gotables file into a TableSet.

func NewTableSetFromGob

func NewTableSetFromGob(buffer []bytes.Buffer) (*TableSet, error)

Reconstruct a TableSet from a slice of []bytes.Buffer

Each element in the slice is a Gob encoded table as a slice of []byte

Calls GobDecodeTableSet(buffer)

Note: GOB encoding and decoding does not (yet) support nested tables or type time.Time.

func NewTableSetFromJSON

func NewTableSetFromJSON(jsonTableSet string) (tableSet *TableSet, err error)

Unmarshal JSON documents to a *gotables.TableSet

Example
//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))
var err error

tableSetString := `
	[[TwoTablesComingUp]]

	[MyTable]
	x int = 1
	y int = 2
	z int = 3

	[YourTable]
	a float32 = 1
	b float32 = 2
	c float32 = 3
	`
tableSet1, err := NewTableSetFromString(tableSetString)
if err != nil {
	log.Println(err)
}

fmt.Println(tableSet1)

var jsonString string
jsonString, err = tableSet1.GetTableSetAsJSONIndent()
if err != nil {
	log.Println(err)
}

fmt.Println(jsonString)
fmt.Println()

tableSet2, err := NewTableSetFromJSON(jsonString)
if err != nil {
	log.Println(err)
}

fmt.Println(tableSet2)

equals, err := tableSet2.Equals(tableSet1)

fmt.Printf("table2.Equals(table1) == %t\n", equals)
Output:

[[TwoTablesComingUp]]

[MyTable]
x int = 1
y int = 2
z int = 3

[YourTable]
a float32 = 1
b float32 = 2
c float32 = 3

{
	"tableSetName": "TwoTablesComingUp",
	"tables": [
		{
			"tableName": "MyTable",
			"isStructShape": true,
			"metadata": [
				{
					"x": "int"
				},
				{
					"y": "int"
				},
				{
					"z": "int"
				}
			],
			"data": [
				[
					{
						"x": 1
					},
					{
						"y": 2
					},
					{
						"z": 3
					}
				]
			]
		},
		{
			"tableName": "YourTable",
			"isStructShape": true,
			"metadata": [
				{
					"a": "float32"
				},
				{
					"b": "float32"
				},
				{
					"c": "float32"
				}
			],
			"data": [
				[
					{
						"a": 1
					},
					{
						"b": 2
					},
					{
						"c": 3
					}
				]
			]
		}
	]
}

[[TwoTablesComingUp]]

[MyTable]
x int = 1
y int = 2
z int = 3

[YourTable]
a float32 = 1
b float32 = 2
c float32 = 3

table2.Equals(table1) == true
Example (ZeroRows)

It is permitted to have zero rows.

//where(fmt.Sprintf("***INSIDE*** %s", UtilFuncName()))
var err error

tableSetString :=
	`[[ZeroRowsTableSet]]

	[MyTable]
	x	y	z
	int	int	int

	[YourTable]
	a		b		c
	float32	float32	float32
	`
tableSet1, err := NewTableSetFromString(tableSetString)
if err != nil {
	log.Println(err)
}

fmt.Println(tableSet1)

var jsonString string
jsonString, err = tableSet1.GetTableSetAsJSONIndent()
if err != nil {
	log.Println(err)
}

fmt.Println(jsonString)
fmt.Println()

tableSet2, err := NewTableSetFromJSON(jsonString)
if err != nil {
	log.Println(err)
}

fmt.Println(tableSet2)

equals, err := tableSet2.Equals(tableSet1)

fmt.Printf("tableSet2.Equals(tableSet1) == %t\n", equals)
Output:

[[ZeroRowsTableSet]]

[MyTable]
  x   y   z
int int int

[YourTable]
      a       b       c
float32 float32 float32

{
	"tableSetName": "ZeroRowsTableSet",
	"tables": [
		{
			"tableName": "MyTable",
			"metadata": [
				{
					"x": "int"
				},
				{
					"y": "int"
				},
				{
					"z": "int"
				}
			],
			"data": []
		},
		{
			"tableName": "YourTable",
			"metadata": [
				{
					"a": "float32"
				},
				{
					"b": "float32"
				},
				{
					"c": "float32"
				}
			],
			"data": []
		}
	]
}

[[ZeroRowsTableSet]]

[MyTable]
  x   y   z
int int int

[YourTable]
      a       b       c
float32 float32 float32

tableSet2.Equals(tableSet1) == true

func NewTableSetFromString

func NewTableSetFromString(s string) (*TableSet, error)

Read and parse a gotables string into a TableSet.

Example (Go113NumericLiteralsBinOctHex)
tableString :=
	`[int_literals]
	decimal binary octal hex single zeros
	int     int    int   int int    int
	10      0b1010 0o12  0xA 0      0
	10      0B1010 0O12  0XA 1      00
	10      0b1010 012   0xa 2      000
	10      0B1010 0012  0xA 3      0000

	[int8_literals]
	decimal binary octal hex  single zeros
	int8    int8   int8  int8 int8   int8
	10      0b1010 0o12  0xA  0      0
	10      0B1010 0O12  0XA  1      00
	10      0b1010 012   0xa  2      000
	10      0B1010 0012  0xA  3      0000

	[uint8_literals]
	decimal binary octal hex   single zeros
	uint8   uint8  uint8 uint8 uint8  uint8
	10      0b1010 0o12  0xA   0      0
	10      0B1010 0O12  0XA   1      00
	10      0b1010 012   0xa   2      000
	10      0B1010 0012  0xA   3      0000

	[any_literals]
	dec int = 11
	bin int = 0b1011
	oct int = 0o13
	hex int = 0xB

	[slice_literals]
	xx                       bb
	[]uint8                  []byte
	[0b1010 0o12 0B1010 0xA] [0xa 0b1010 0o12 012]
	[10 0o12 0b1010 0xA]     [0Xa 0B1010 0o12 012]
	[30]                     [90 81 72]
	[]                       []
	[10]                     [90 81 72 63 255]
	`

tableSet, err := NewTableSetFromString(tableString)
if err != nil {
	log.Println(err)
}

fmt.Println(tableSet)
Output:

[int_literals]
decimal binary octal hex single zeros
    int    int   int int    int   int
     10     10    10  10      0     0
     10     10    10  10      1     0
     10     10    10  10      2     0
     10     10    10  10      3     0

[int8_literals]
decimal binary octal  hex single zeros
   int8   int8  int8 int8   int8  int8
     10     10    10   10      0     0
     10     10    10   10      1     0
     10     10    10   10      2     0
     10     10    10   10      3     0

[uint8_literals]
decimal binary octal   hex single zeros
  uint8  uint8 uint8 uint8  uint8 uint8
     10     10    10    10      0     0
     10     10    10    10      1     0
     10     10    10    10      2     0
     10     10    10    10      3     0

[any_literals]
dec int = 11
bin int = 11
oct int = 11
hex int = 11

[slice_literals]
xx            bb
[]uint8       []byte
[10 10 10 10] [10 10 10 10]
[10 10 10 10] [10 10 10 10]
[30]          [90 81 72]
[]            []
[10]          [90 81 72 63 255]
Example (WithTableSetName)
var err error
var tableSet *TableSet
var tableSetString string

tableSetString =
	`[[MyTableSetName]]
	[MyTable1]
	x	y	z
	int	int	int
	1	3	9
	5	10	15

	[MyTable2]
	a int = 1
	b int = 2
	c int = 3
	`
tableSet, err = NewTableSetFromString(tableSetString)
if err != nil {
	fmt.Println(err)
}

// Note: this does not fail.
expected := "MyTableSetName"
found := tableSet.Name()
if found != expected {
	fmt.Printf("Expecting parsed tableset name to be %q, but found: %q", expected, found)
}

fmt.Println(tableSet.String())
Output:

[[MyTableSetName]]

[MyTable1]
  x   y   z
int int int
  1   3   9
  5  10  15

[MyTable2]
a int = 1
b int = 2
c int = 3

func (*TableSet) Append

func (tableSet *TableSet) Append(newTable *Table) error

func (*TableSet) AppendTable

func (tableSet *TableSet) AppendTable(newTable *Table) error

Add a table to a table set.

func (*TableSet) Copy

func (tableSet *TableSet) Copy(copyRowsAlso bool) (*TableSet, error)

Create a copy of TableSet, with or without copying table rows of data.

func (*TableSet) DeleteTable

func (tableSet *TableSet) DeleteTable(tableName string) error

func (*TableSet) DeleteTableByTableIndex

func (tableSet *TableSet) DeleteTableByTableIndex(tableIndex int) error

func (*TableSet) Equals

func (tableSet1 *TableSet) Equals(tableSet2 *TableSet) (bool, error)

Check whether tableSet1 and tableSet2 are the same.

func (*TableSet) FileName

func (tableSet *TableSet) FileName() string

The file name if this TableSet has been created from a file. Otherwise ""

func (*TableSet) GetTableSetAsJSON

func (tableSet *TableSet) GetTableSetAsJSON() (jsonTableSet string, err error)

Marshal gotables TableSet to JSON

func (*TableSet) GetTableSetAsJSONIndent

func (tableSet *TableSet) GetTableSetAsJSONIndent() (jsonTableSetIndented string, err error)

func (*TableSet) GobEncode

func (tableSet *TableSet) GobEncode() ([]bytes.Buffer, error)

Note: GOB encoding and decoding does not (yet) support nested tables or type time.Time.

Example (Tableset)

GOB

s := `[sable_fur]
    i   s       f           b
    int string  float64     bool
    1   "abc"   2.3         true
    2   "xyz"   4.5         false
    3   "ssss"  4.9         false

	[Struct_With_Data]
	Fred int = 42
	Wilma int = 39
	Pebbles int = 2

	[Empty_Struct]
	Fred int

	[Empty_Table]
	Fred
	int
	`
tableSetToEncode, err := NewTableSetFromString(s)
if err != nil {
	log.Println(err)
}
fmt.Println("(1) TableSet ready to encode into binary.")
fmt.Println(tableSetToEncode)

// Encode into binary.
var binary []bytes.Buffer
binary, err = tableSetToEncode.GobEncode()
if err != nil {
	log.Println(err)
}

// Now decode it back from binary to type *gotables.TableSet
tableSetDecoded, err := GobDecodeTableSet(binary)
if err != nil {
	log.Println(err)
}
fmt.Println("(2) TableSet decoded from binary.")
fmt.Println(tableSetDecoded)

equals, err := tableSetDecoded.Equals(tableSetToEncode)
if err != nil {
	fmt.Println(err)
}
fmt.Printf("tableSetDecoded.Equals(tableSetToEncode) = %t\n", equals)
Output:

(1) TableSet ready to encode into binary.
[sable_fur]
  i s            f b
int string float64 bool
  1 "abc"      2.3 true
  2 "xyz"      4.5 false
  3 "ssss"     4.9 false

[Struct_With_Data]
Fred int = 42
Wilma int = 39
Pebbles int = 2

[Empty_Struct]
Fred int

[Empty_Table]
Fred
 int

(2) TableSet decoded from binary.
[sable_fur]
  i s            f b
int string float64 bool
  1 "abc"      2.3 true
  2 "xyz"      4.5 false
  3 "ssss"     4.9 false

[Struct_With_Data]
Fred int = 42
Wilma int = 39
Pebbles int = 2

[Empty_Struct]
Fred int

[Empty_Table]
Fred
 int

tableSetDecoded.Equals(tableSetToEncode) = true

func (*TableSet) HasTable

func (tableSet *TableSet) HasTable(tableName string) (bool, error)

Checks whether table exists

func (*TableSet) IsValidTableSet

func (tableSet *TableSet) IsValidTableSet() (bool, error)

func (*TableSet) Name

func (tableSet *TableSet) Name() string

func (*TableSet) RenameTable

func (tableSet *TableSet) RenameTable(renameFrom string, renameTo string) error

func (*TableSet) SetFileName

func (tableSet *TableSet) SetFileName(fileName string)

func (*TableSet) SetName

func (tableSet *TableSet) SetName(tableSetName string) error

func (*TableSet) String

func (tableSet *TableSet) String() string

Returns a set of parsable tables with format right-aligned (numbers) as a string.

Example
// Deliberately unpadded (by hand) for contrast.
s := `[sable_fur]
    i s f b
    int string float64 bool
    1 "abc" 2.3 true
    2 "xyz" 4.5 false
    3 "ssss" 4.9 false
	`
tableSet, err := NewTableSetFromString(s)
if err != nil {
	log.Println(err)
}

// Imagine this function (in both TableSet and Table) is called StringPaddedAndAligned()
// It isn't, because it has to be called String(), but that's the functionality.

// Notice that the default String() output for both TableSet and Table objects
// is padded into easy to read columns, with numeric columns aligned right.
// The design is: readability trumps compactness.
// There are alternatives where size matters, such as compression, and StringUnpadded()

fmt.Println("(1) TableSet (and Table) default String() output:")
fmt.Println(tableSet.String())

fmt.Println("(2) TableSet (and Table) same as default String() output:")
fmt.Println(tableSet)
Output:

(1) TableSet (and Table) default String() output:
[sable_fur]
  i s            f b
int string float64 bool
  1 "abc"      2.3 true
  2 "xyz"      4.5 false
  3 "ssss"     4.9 false

(2) TableSet (and Table) same as default String() output:
[sable_fur]
  i s            f b
int string float64 bool
  1 "abc"      2.3 true
  2 "xyz"      4.5 false
  3 "ssss"     4.9 false

func (*TableSet) StringPadded

func (tableSet *TableSet) StringPadded() string

func (*TableSet) StringUnpadded

func (tableSet *TableSet) StringUnpadded() string
Example
// Deliberately padded (by hand) for contrast.
s :=
	`[wombat_fur]
	  i s            f b
	int string float64 bool
	  1 "abc"      2.3 true
	  2 "xyz"      4.5 false
	  3 "s  s"     4.9 false

	[various]
	i   f       u    s
	int float32 uint string
	3   44.55   2    "Here I am!"
	4   22.99   255  "And now I'm not ..."
	`
tableSet, err := NewTableSetFromString(s)
if err != nil {
	log.Println(err)
}

// Note: the default String() output for both TableSet and Table objects
// is padded into easy to read columns, with numeric columns aligned right.
// The design is: readability trumps compactness.
// There are alternatives where size matters, such as compression, and StringUnpadded()

// This is an example of StringUnpadded() which uses minimal spacing between values.

fmt.Println("TableSet (and Table) StringUnpadded() output:")
fmt.Println(tableSet.StringUnpadded())
Output:

TableSet (and Table) StringUnpadded() output:
[wombat_fur]
i s f b
int string float64 bool
1 "abc" 2.3 true
2 "xyz" 4.5 false
3 "s  s" 4.9 false

[various]
i f u s
int float32 uint string
3 44.55 2 "Here I am!"
4 22.99 255 "And now I'm not ..."

func (*TableSet) Table

func (tableSet *TableSet) Table(tableName string) (*Table, error)

func (*TableSet) TableByTableIndex

func (tableSet *TableSet) TableByTableIndex(tableIndex int) (*Table, error)

func (*TableSet) TableCount

func (tableSet *TableSet) TableCount() int

func (*TableSet) TableIndex

func (tableSet *TableSet) TableIndex(tableName string) (int, error)

func (*TableSet) WriteFile

func (tableSet *TableSet) WriteFile(fileName string, mode os.FileMode) error

Write a TableSet to a text file.

type TableSetExported

type TableSetExported struct {
	TableSetName string
	FileName     string
}

For GOB. Selected header information for exporting.

type UtilStringFlag

type UtilStringFlag struct {
	// contains filtered or unexported fields
}

UtilStringFlag implements the flag.Value interface https://golang.org/pkg/flag/#Value

type Value interface {
	String() string
	Set(string) error
}

func (*UtilStringFlag) AllOk

func (sf *UtilStringFlag) AllOk() bool

AllOk() is specific to gotables.Util It means:-

(1) flag exists
(2) flag is set
(3) error is nil

func (*UtilStringFlag) Error

func (sf *UtilStringFlag) Error() error

Error() is specific to gotables.Util

func (*UtilStringFlag) Exists

func (sf *UtilStringFlag) Exists() bool

Exists() is specific to gotables.Util

func (*UtilStringFlag) IsSet

func (sf *UtilStringFlag) IsSet() bool

IsSet() is specific to gotables.Util

func (*UtilStringFlag) Print

func (sf *UtilStringFlag) Print()

Print to stdout UtilStringFlag field values and method results.

func (*UtilStringFlag) Set

func (sf *UtilStringFlag) Set(s string) error

Set() implements part of the flag.Value interface https://golang.org/pkg/flag/#Value

func (*UtilStringFlag) String

func (sf *UtilStringFlag) String() string

String() implements part of the flag.Value interface https://golang.org/pkg/flag/#Value

Directories

Path Synopsis
cmd
gotecho
Echo the tables of gotables files.
Echo the tables of gotables files.
gotsyntax
Check the syntax of gotables files.
Check the syntax of gotables files.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL