tagged: golang

Golang regex basics: Match and find

You can create a regular expressions conforming to RE2 using the Compile or MustCompile method on regexp.
rp := regexp.MustCompile("[a-z]+")
rp1, err := regexp.Compile("[a-z]+")

The first panics if the regex is incorrect. The second returns an error message if the regex is incorrect.
You can match with MatchString(str). If you omit the String in the method name, it will expect a byte array.
foundBool := rp.MatchString("abc")

The Find methods -- and others -- confirm to this general pattern.
rp.FindString("abc def") // "abc"
rp.FindAllString("abc def", -1) // ["abc", "def"]

If you have the word Submatch (FindAllSubmatch) it will give you any groups in the match, as two dimensional slice.
rp := regexp.MustCompile("([a-z])([a-z])[a-z]+")
rp.FindAllStringSubmatch("abc") // ["abc", "a", "b"]
If you have the word Index at the end it will return a int slice with the starting and ending point of the match, including groups
rp := regexp.MustCompile("([a-z])([a-z])[a-z]+")
rp.FindAllStringSubmatchIndex("abc") // [0, 3, 0, 1, 1, 2]

The first two ints are the start and end of the match. The next two are the next group match. The next two likewise.

golang golang-regex

Golang: Constants, enums and iota

You can type or untype your constants. And untyped constant can be used in any expression and converted implicitly:
const thing = 5 // untyped
const thing2 int = 5 // typed - only used in int expressions

Enums come by putting a bunch of consts in parens:
const ( 
	One = 1
	Two = 2
	Three = 4

You can use iota to create these values. Within a const group, it starts at 0, and then increments for each expression.
const ( 
	One = 1 << iota // 1 (i.e. 1 << 0)
	Two // 2 (i.e. 1 << 1)
	Three // 4 (i.e 1 << 2)

If you print a Two, for example, it will display 2.
You can 1) Give the enum a custom type and 2) give the custom type a String() method to change that:
Giving custom types methods is the OOP of golang. And will be discussed in later posts.
type Type int

const ( 
	One Type = 1 << iota // 1
	Two Type // 2 (i.e. 1 << 1)
	Three Type // 4 (i.e 1 << 2)

func (t Type) String() string {
	if t&One==One {
	return s

Now if you print the 'One' type it will out the text "One".


Enable synax colouring in Vim with Golang

Put this in your .vimrc

filetype off
filetype plugin indent off
set runtimepath+=$GOROOT/misc/vim
filetype plugin indent on
syntax on

First turn off filetype and filetype plugin indent. This will force it to reload when we include something new in the runtime path apparently.
Then set the runtimepath to include the golang installation directory. The vim files are there.
Then turn the filetype plugin indent on and the synax on.

golang vim

Golang: Panic and recover

When a panic("something") is called the program will exit.
Just before doing so, all the functions in the stack are immediately exited just before calling all of the deferred statements in each.

            func letUsPanic() {
                    defer func(s string) {
                            fmt.Println("This will be called)
                    fmt.Println("This will never be called")

If the above was called from main(), then none of main's statements after letUsPanic() would be called either, except any deferred statements in main().
We can 'recover' from a panic, however, if we put a 'recover()' statement in a deferred statement.

            func letUsPanic() {
                    defer func() {
                            if e := recover(); e != nil {
                                    // e is the interface{} typed-value we passed to panic()
                                    fmt.Println("Whoops: ", e) // Prints "Whoops: boom!"
                    fmt.Println("This will never be called")

Now if we run letUsPanic() from main(), the methods below letUsPanic() would be called.
It's bad style to use these. Go doesn't do exceptions as some languages do. Go uses errors and multiple return values.
This is mostly used, for example, at the root level in web services that should live forever, regardless of a completley unexpected panic occurring in a goroutine.


Golang: interface{}, type assertions and type switches

An interface{} type is a type that could be any value. It's like Object in Java.

            var anything interface{} = "string"
            var moreAnything interface{} = 123

This means you can create a function that can accept any type, custom or internal.
You can't use a 'type conversion' here since they're not similar types. You must use a type assertion:

            aString := anything.(string)

We convert the 'anything' interface{} type using a dot and the required type in parentheses.
If it fails, golang will panic and fail (unless you 'recover' from the panic). You can get around this by passing back two parameters:

            aString, found := anything.(string)

Now if the assertion fails, it won't panic and crash, but will set found to false.
If you're not sure about what the interface{} type could be, you can use a type switch:

            switch v := anything.(type) {
                    case string:
                    case int32, int64:
                    case SomeCustomType:

Instead of putting the type in parentheses, you place the text 'type'. The return value will be actual value of 'anything'.
Now each case has possible types.
(Note that golang doesn't need 'break' after each case. It does that automatically. You use 'fallthrough' statement to fallthrough ot the next case.)
You normally would use polymorphism instead of this. But it can be useful, for example, in cases where you're dealing with unknown external data.


Page 1 of 5