I am trying to build a simple webserver. I want to replace all \n with <br>.
I wanted to use bytes for this, because my page body is stored as an []byte.
I use bytes.ReplaceAll() for this. But it keeps saying that it's a reference to undefined identifier.
Can someone tell me why? I tried the exact same line within an online Compiler and it worked just fine. Do I miss the library?
See my code below:
import (
"bytes"
"html/template"
"io/ioutil"
"log"
"net/http"
"regexp"
)
type Page struct {
Title string
Body []byte
}
func editHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := loadPage(title)
if err != nil {
p = &Page{Title: title}
}
// THE LINE THAT CAUSES TROUBLE
p.Body = bytes.ReplaceAll(p.Body, []byte("\n"), []byte("<br>"))
renderTemplate(w, "edit", p)
}
The bytes package is part of the standard library, so it is unlikely that you don't have it if you have the go tool available to you.
But do note that bytes.ReplaceAll() was added in Go 1.12, so if you have an older Go SDK, this function will not be available to you.
Execute go version to find out. Get the latest Go from the official site: https://golang.org/dl/
Further to icza's answer,
For the benefit of Go versions prior to 1.12, the following are equivalent:
bytes.ReplaceAll(a, b, c)
and
bytes.Replace(a, b, c, -1)
See the implementation of ReplaceAll
Related
Edit: Please be so kind and read the question before you judge it. Answers like "It typechecks your code" are not helpful and only show that you have not understood the question. This question is not about a typo, it is about the (partial) implementation of the semantics of golang.
I am starting to learn go and thus I am trying to explore the basics of the language.
If I use this statement:
fmt.Println(1 + true)
in Visual Studio Code, I get "invalid operation: 1 + true (mismatched types untyped int and untyped bool)", before running my program.
I am totally fine with the error message, but I am wondering how VSC knows that before compilation.
Go's parser should be happy with this line, since there is no type restriction (like allowing only numeric expressions as operands of "+") in go's grammar:
Expression = UnaryExpr | Expression binary_op Expression .
UnaryExpr = PrimaryExpr | unary_op UnaryExpr .
binary_op = ... | add_op | ... .
add_op = "+" | ... .
So, I am wondering, what is going on here? is there a separate step of type-checking in go's compiler that VSC uses or did VSC write its own type checker?
VSCode uses a language server for language-aware IDE features like autocompletion, diagnostics, jump-to definition, etc.
For Go, the language server implementation is gopls. If you're really curious, feel free to check out the source code of the vscode-go extension, however if you're just learning Go perhaps you have better things to do :-)
The extension is written in TypeScript (like most of VSCode), though gopls is written in Go. It uses Go tooling which supports parsing and type checking Go code with the go/types package. You are correct that for this specific error, type checking is required; just parsing is insufficient.
Here's a basic example of using go/types to typecheck Go code:
package main
import (
"fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
)
const hello = `package main
import "fmt"
func main() {
fmt.Println("Hello, world")
}`
func main() {
fset := token.NewFileSet()
// Parse the input string, []byte, or io.Reader,
// recording position information in fset.
// ParseFile returns an *ast.File, a syntax tree.
f, err := parser.ParseFile(fset, "hello.go", hello, 0)
if err != nil {
log.Fatal(err) // parse error
}
// A Config controls various options of the type checker.
// The defaults work fine except for one setting:
// we must specify how to deal with imports.
conf := types.Config{Importer: importer.Default()}
// Type-check the package containing only file f.
// Check returns a *types.Package.
pkg, err := conf.Check("cmd/hello", fset, []*ast.File{f}, nil)
if err != nil {
log.Fatal(err) // type error
}
fmt.Printf("Package %q\n", pkg.Path())
fmt.Printf("Name: %s\n", pkg.Name())
fmt.Printf("Imports: %s\n", pkg.Imports())
fmt.Printf("Scope: %s\n", pkg.Scope())
}
I am using a package: ccs08
In my main, I am importing the package and using some of its functions. I have followed the usage from the unit tests given:
package main
import(
"fmt"
"math/big"
"crypto/rand"
"zkrp/ccs08"
"zkrp/crypto/bn256"
)
func main(){
var (
r *big.Int
s []int64
)
s = make([]int64, 4)
s[0] = 12
s[1] = 42
s[2] = 61
s[3] = 71
p, _ := ccs08.SetupSet(s)
r, _ = rand.Int(rand.Reader, bn256.Order)
proof_out, _ := ccs08.ProveSet(12, r, p)
result, _ := ccs08.VerifySet(&proof_out, &p)
if result != true {
fmt.Println("not verified")
}
}
I then have a similar main file,main2, where I am using another set of functions from the same package. This does NOT work
package main
import(
"fmt"
"math/big"
"crypto/rand"
"zkrp/ccs08"
"zkrp/crypto/bn256"
)
func main(){
var (
result bool
zkrp ccs08
)
zkrp.Setup(347184000, 599644800)
zkrp.x = new(big.Int).SetInt64(419835123)
zkrp.r, _ = rand.Int(rand.Reader, bn256.Order)
e := zkrp.Prove()
result, _ = zkrp.Verify()
if result != true {
fmt.println("not verified")
}
}
I am getting this error:
./main2.go:7: imported and not used: "zkrp/ccs08".
./main2.go:16: use of package ccs08 without selector.
What am I doing wrong?
For the first file, everything works because the code is using public members of the ccs08 package. However, this is not the case for the second file.
You mentioned the code in the second file is copied from here.
To understand why the code does not work when pasted into a main method outside the ccs08 package, you need to understand what it is doing in its original location. Specifically this part:
var (
result bool
zkrp ccs08
)
In the original location (inside the ccs08 package) there is a private struct type named ccs08. The declaration can be seen here. What the above code is doing is creating a variable named zkrp the type of which is the private struct type ccs08. Then, the various functions called on the variable are methods bound to this private struct (you can see the methods here).
Now, in the code you posted (after pasting into a location outside the ccs08 package), there is no way to access the private ccs08 struct (I can't even find a public method which returns it in the zkrp source code). So, what Go sees when it tries to execute this code is a typo (where it thinks you are trying to write something of the form package.Member):
// this looks like you wanted to declare a variable with type:
// "ccs08.SomeType" but forgot to write ".SomeType"
// Thus Go gives the error: "use of package ccs08 without selector"
var zkrp ccs08
And the "imported and not used" error is because the ccs08 package isn't used in a valid way anywhere in the code.
The code which you copied is honestly pretty confusing with all the reusing of the strings ccs08 and zkrp for naming of different things. I hope this clears it up a bit.
I was having a problem with the strings.Builder type in GO.
Attempted to run the example code verbatim and GO still responds with:
undefined: strings.Builder
Any clues as to what the problem can be, there's been not other problems at all.
package main
import (
"fmt"
"strings"
)
func main() {
var b strings.Builder
for i := 3; i >=1; i-- {
fmt.Fprintf(&b, "%x...", i)
}
b.WriteString("ignition")
fmt.Println(b.String())
}
strings.Builder was added in Go 1.10 (released 2018-02-16, 9 days ago at the time of writing). If you are building using an older version of Go, it won't be available.
If must working with older Go version, you can use bytes.Buffer instead.
I'm having issues importing "golang.org/x/net/html" it's simply telling me it can't find the package. Looking around the internet has only confused me more with some people saying that you can't use it anymore, some people saying to do this: Install exp/html in Go and some people saying that just using "golang.org/x/net/html" works just fine.
Here is just a small part of the code I'm trying to run:
package main
import (
"fmt"
"html"
"net/http"
"golang.org/x/net/html"
"os"
"strings"
)
// Helper function to pull the href attribute from a Token
func getHref(t html.Token) (ok bool, href string) {
// Iterate over all of the Token's attributes until we find an "href"
for _, a := range t.Attr {
if a.Key == "href" {
href = a.Val
ok = true
}
}
return
}
It obviously won't let me use the html token because I can't import the package.
You can execute at the command line “go get golang.org/x/net/html”
You can take a look at https://golang.org/doc/code.html. It contains a very good description on how to start coding in Go. The issues you are mentioning are described there.
So, you set GOROOT to your installation path. Then you set GOPATH to your go workspace(s), which obey the bin, pkg, src structure. The first entry in your GOPATH is used to store the go get ... which you install on your machine.
This might be a very amateur question. I'm trying to embed static files into binary, ie. html. How do I do that with https://github.com/jteeuwen/go-bindata?
So I can access an asset with this https://github.com/jteeuwen/go-bindata#accessing-an-asset, but what do I do with "data", and how to do I parse files, execute template, and serve them in the directory?
I couldn't find any examples online, and will appreciate some help!
5/6 years later, this should be easier with Go 1.16 (Q1 2021), which adds support for embedded files (issue/proposal 41191 )
It will be permitted to use //go:embed naming a single file to initialize a plain string or []byte variable:
//go:embed gopher.png
var gopherPNG []byte
The import is required to flag the file as containing //go:embed lines and needing processing.
Goimports (and gopls etc) can be taught this rule and automatically add the import in any file with a //go:embed as needed.
That sparked a debate on issue 42328 about how to avoid surprising inclusion of "hidden" files when using //go:embed
This as resolved in CL 275092 and commit 37588ff
Decision to exclude files matching .* and _* from embedded directory results when embedding an entire directory tree.
See src/embed/internal/embedtest/embed_test.go
//go:embed testdata/k*.txt
var local embed.FS
testFiles(t, local, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/k*.txt
var s string
testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/h*.txt
var b []byte
testString(t, string(b), "local variable b", "hello, world\n")
Note: with CL 281492, cmd/go passes embedcfg to gccgo if supported.
See also (Jan. 2021) issue 43854 "opt-in for //go:embed to not ignore files and empty dirs".
Given a directory structure like so:
example/
main.go
data/hi.html
example/main.go
package main
import (
"html/template"
"log"
"net/http"
"os"
)
var tmpl *template.Template
func init() {
data, err := Asset("data/hi.html")
if err != nil {
log.Fatal(err)
}
tmpl = template.Must(template.New("tmpl").Parse(string(data)))
}
func main() {
// print to stdout
tmpl.Execute(os.Stdout, map[string]string{"Name": "James"})
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
tmpl.Execute(w, map[string]string{"Name": "James"})
})
log.Fatal(http.ListenAndServe(":8000", nil))
}
example/data/hi.html
<h1>Hi, {{.Name}}</h1>
run like so:
go-bindata data && go build && ./example
Console Output:
<h1>Hi, James</h1>
HTTP output:
Hi, James