Golang : functional programming in Go - regex

I tried something I did in Javascript.
But it says
http://play.golang.org/p/qlWLI03Dnl
package main
import "fmt"
import "regexp"
import "strings"
func swapit(str string) string {
var validID = regexp.MustCompile(`[a-z]|[A-Z]`)
return validID.ReplaceAllString(str, func(${0}, ${1}, ${2}) string {
return (${1}) ? strings.ToUpper(${0}) : strings.ToLower(${0})
})
}
func main() {
fmt.Println(swapit("hello wOrld."))
// HELLO WoRLD.
}
I also tried this removing ? : syntax but still does not work.
http://play.golang.org/p/mD6_78zzo1
Does really go not support this? Do I just give up and just bruteforce each character to change cases?
Thanks a lot

As #James Henstridge already pointed out, there are multiple problems with your code. This answer will not focus on the errors, but rather a different way of solving the problem.
If your aim is to learn about using regexp in Go, this answer of mine is useless.
If your aim is to get learn how to make a function that swaps cases, then I suggest a solution without regexp, utilizing the unicode package instead:
package main
import (
"bytes"
"fmt"
"unicode"
)
func SwapCase(str string) string {
b := new(bytes.Buffer)
for _, r := range str {
if unicode.IsUpper(r) {
b.WriteRune(unicode.ToLower(r))
} else {
b.WriteRune(unicode.ToUpper(r))
}
}
return b.String()
}
func main() {
fmt.Println(SwapCase("Hej värLDen."))
}
Output:
hEJ VÄRldEN.
Playground
This solution will handle all non A-Z characters as well, such as ö-Ö and å-Å.

Related

How to unit test CLI output [duplicate]

This question already has answers here:
How to test a function's output (stdout/stderr) in unit tests
(3 answers)
Closed 3 years ago.
I work on a small CLI application. I am trying to write unit tests. I have a function that renders some output as a table to the command line using fmt.Println/fmt.Printf. I am wondering how I can capture that output in a unit test to make sure I am getting what is expected? Below is just a barebone skeleton that somewhat represents what I am trying to achieve.
main.go
package main
import (
"fmt"
"io"
)
func print() {
fmt.Println("Hello world")
}
func main() {
print()
}
main_test.go
package main
import "testing"
func TestPrint(t *testing.T) {
expected := "Hello world"
print() // somehow capture the output
// if got != expected {
// t.Errorf("Does not match")
// }
}
I have tried a few approaches such as How to check a log/output in go test? but with minimal luck but, that could be due to misunderstanding on my end.
you got to inject, somehow, the destination writer.
Your API is insufficient because it does not allow injection.
In this modified code, the destination writer is given as an argument, but other API implementation decision are possible.
package main
import (
"fmt"
"io"
)
func print(dst io.Writer) {
fmt.Fprintln(dst, "Hello world")
}
func main() {
print(os.Stdout)
}
you can test doing so
package main
import "testing"
func TestPrint(t *testing.T) {
expected := "Hello world"
var b bytes.Buffer
print(&b) // somehow capture the output
// if b.String() != expected {
// t.Errorf("Does not match")
// }
}
bytes.Buffer implements io.Writer and can be used as a stub to capture execution results.
https://golang.org/pkg/bytes/#Buffer

turn reflect into comparable data

I want to be able to compare the type of an object using reflect. Here is my code:
package main
import (
"fmt"
"reflect"
)
func main() {
tst := "cat"
if reflect.TypeOf(tst) == string {
fmt.Println("It's a string!")
}
}
This gives me an error type string is not an expression. How can I fix this only using reflect? (no type switches, etc.)
Two simple options:
use Kind:
if reflect.TypeOf(tst).Kind() == reflect.String {
fmt.Println("It's a string!")
}
use TypeOf another string:
if reflect.TypeOf(tst) == reflect.TypeOf("") {
fmt.Println("It's a string!")
}
However, personally I'd prefer a type switch or type check (i.e. if _, ok := tst.(string); ok {...}

Go, regexp : to match either case and keep the original text

I want to replace regex-matched strings with new string but still keeping part of the original text.
I want to get
I own_VERB it and also have_VERB it
from
I own it and also have it
how do I do this with one line of code? I tried but can't get further than this. Thanks,
http://play.golang.org/p/SruLyf3VK_
package main
import "fmt"
import "regexp"
func getverb(str string) string {
var validID = regexp.MustCompile(`(own)|(have)`)
return validID. ReplaceAllString(str, "_VERB")
}
func main() {
fmt.Println(getverb("I own it and also have it"))
// how do I keep the original text like
// I own_VERB it and also have_VERB it
}
You don't even need a capture group for this.
package main
import "fmt"
import "regexp"
func getverb(str string) string {
var validID = regexp.MustCompile(`own|have`)
return validID. ReplaceAllString(str, "${0}_VERB")
}
func main() {
fmt.Println(getverb("I own it and also have it"))
// how do I keep the original text like
// I own_VERB it and also have_VERB it
}
${0} contains the string which matched the whole pattern; ${1} will contain the string which matched the first sub-pattern (or capture group) if there is any, and which you can see in Darka's answer.
Seems a bit googling helps:
var validID = regexp.MustCompile(`(own|have)`)
return validID. ReplaceAllString(str, "${1}_VERB")
Inside replacement, $ signs are interpreted as in Expand, so for instance $1 represents the text of the first submatch.
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("(own|have)")
fmt.Println(re.ReplaceAllString("I own it and also have it", "${1}_VERB"))
}
Output
I own_VERB it and also have_VERB it

Golang regex replace does nothing

I want to replace any non-alphanumeric character sequences with a dash. A snippet of what I wrote is below. However it does not work and I'm completely clueless why. Could anyone explain me why the snippet behaves not like I expect it to and what would be the correct way to accomplish this?
package main
import (
"fmt"
"regexp"
"strings"
)
func main() {
reg, _ := regexp.Compile("/[^A-Za-z0-9]+/")
safe := reg.ReplaceAllString("a*-+fe5v9034,j*.AE6", "-")
safe = strings.ToLower(strings.Trim(safe, "-"))
fmt.Println(safe) // Output: a*-+fe5v9034,j*.ae6
}
The forward slashes are not matched by your string.
package main
import (
"fmt"
"log"
"regexp"
"strings"
)
func main() {
reg, err := regexp.Compile("[^A-Za-z0-9]+")
if err != nil {
log.Fatal(err)
}
safe := reg.ReplaceAllString("a*-+fe5v9034,j*.AE6", "-")
safe = strings.ToLower(strings.Trim(safe, "-"))
fmt.Println(safe) // Output: a*-+fe5v9034,j*.ae6
}
(Also here)
Output
a-fe5v9034-j-ae6

Golang Regular Expressions - what am I doing incorrectly?

As a personal project, trying to learn Go(lang) by applying it to something, I am writing an EMCAScript/JavaScript "compiler"; all it will (initially) do is allow you to include other .js files.
Functionality aside, I am pulling my hair out trying to figure out the regexp package. Here is the snippet that does not seem to be doing what I want it to:
// Note: "lines" is an array of strings.
var includeRegex, _ = regexp.Compile("^[ \t]*include[(]{1}\"([^\"]+)\"[)]{1};")
for _, line := range lines {
var isInclude = includeRegex.Match([]byte(line))
if isInclude {
var includeFile = includeRegex.FindString(line)
fmt.Println("INCLUDE", includeFile)
} else {
// ...
}
I have already stumbled across Go's subset of regular expressions, hence why the regex does not read as ^\s*include\("([^"]+)"\);. I have already tested both the preferred, and the Go-style regex, in RegexPal, and both definitely work. The match just never seems to occurr; what am I doing wrong?
For what it's worth, the include() statement I am trying to parse looks like so:
include("somefile.js");
EDIT: For what it's worth, I am keeping the code here.
This seems to work with the latest weekly
package main
import (
"fmt"
"log"
"regexp"
"strings"
)
func main() {
includeRegex, err := regexp.Compile(`^\s*include\("(\\\"|[^"])+"\);`)
if err != nil {
log.Fatal(err)
}
for _, line := range strings.Split(`
foo
include "abc.def"
include("file.js");
include "me\"to\""
include("please\"!\"");
nothing here
`, "\n") {
if includeRegex.Match([]byte(line)) {
includeFile := includeRegex.FindString(line)
fmt.Println("INCLUDE", includeFile)
} else {
fmt.Printf("no match for \"%s\"\n", line)
}
}
}
Output:
$ go build && ./tmp
no match for ""
no match for "foo"
no match for "include "abc.def""
INCLUDE include("file.js");
no match for " include "me\"to\"""
INCLUDE include("please\"!\"");
no match for " nothing here "
no match for ""
$
Try putting the following line at the start of your program:
println(runtime.Version())
It should print weekly.2012-03-13 or something close to that date.