How to include file which in different folder in go templates - go-templates

For example there is test.tpl in folder A:
{{define "test"}} hello I am test {{end}}
another index.tpl in folder B:
{{template "A/test"}} or {{template "test"}}
Both do not work.

Use template.ParseFiles and to parse all templates. Use different names for each. This directory layout
.
├── A
│   └── index-A.tpl
├── B
│   └── index-B.tpl
└── main.go
With A/index-A.tpl containing
A
and B/index-B.tpl containing
B1
{{template "index-A.tpl"}}
B2
used by this code
package main
import (
"os"
"text/template"
)
func main() {
t, err := template.ParseFiles("B/index-B.tpl", "A/index-A.tpl")
if err != nil {
panic(err)
}
err = t.Execute(os.Stdout, nil)
if err != nil {
panic(err)
}
}
will produce this output:
B1
A
B2
Note that both templates are named in templateParseFiles and that B/index-B.tpl references index-a.tpl by name without the path.

Related

Split main.rs into files that refer each other

I have the following structure:
|-- Cargo.toml
|-- src
| |-- file1.rs
| |-- file2.rs
| `-- main.rs
src/file1.rs
pub fn function1() {}
src/file2.rs
// ERROR (1): error[E0583]: file not found for module `file1`
// mod file1;
use crate::file1;
pub fn function2() {
file1::function1();
}
src/main.rs
// ERROR (2): no `file1` in the root
// use crate::file1;
mod file1;
mod file2;
fn main() {
file1::function1();
file2::function2();
}
Basically, I have a different way to import function1, depending on the fact that I am in the crate root or in an arbitrary Rust file (please see ERROR (1) and ERROR (2)).
I am a bit lost on how Rust manages arbirary files: they behave differently from the root crate, where a simple mod keyword does the trick.
So, the mentioned answer for which this is a duplicate only partially only answers how to refer a file from the crate root, not why referring the same file from another one should be different (use crate::<filename>).

Modern CMake Library containing sub-libraries

I have several libraries (subproject) as part of one main library. How can I aggregate the sub-libraries (b) in a "main-library" (a)?
The Goal would be to only have a library a and use the sublibraries as follows #include <b/b.h>
(is there a way to have the include paths as follows: #include <a/b/b.h> ?)
assuming the following folder structure:
a
|-- CMakeLists.txt
|-- aConfig.cmake
`-- b
|-- CMakeLists.txt
|-- include
| `-- b
| `-- b.h
`-- src
`-- b.cpp
I have the following library a depending on library b. library a must be installed and thus found with the find_package(a CONFIG REQUIRED) command in a modern CMake way. The library does not provide any implementation but should aggregate the sublibraries. I thought that making the target_include_directories Public would propagate the INTERFACE_INCLUDE_DIRECTORIES property to the library a since it links against b but I could not manage to get it to work:
cmake_minimum_required(VERSION 3.0.2)
project(a)
find_package(Eigen3 3.2.2 REQUIRED)
add_subdirectory(b)
## Build
add_library(a)
add_library(a::a ALIAS a)
target_link_library(a
PUBLIC
b::b
)
## Install
include(GNUInstallDirs)
# create export set
install(TARGETS a
EXPORT "aTargets"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
install(
DIRECTORY
b/include/
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}"
)
install(EXPORT "${PROJECT_NAME}Targets"
FILE
"aTargets.cmake"
NAMESPACE
"a::"
DESTINATION
lib/cmake/a
)
install(
FILES
"aConfig.cmake"
DESTINATION
"lib/cmake/a"
)
Using interface libraries together with relocatable packages seem to solve your problem. Below is a minimal working example.
Assume that we have the following directory structure
.
├── a
│ ├── b
│ │ ├── CMakeLists.txt
│ │ ├── include
│ │ │ └── b
│ │ │ └── b.h
│ │ └── src
│ │ └── b.cpp
│ ├── c
│ │ ├── CMakeLists.txt
│ │ ├── include
│ │ │ └── c
│ │ │ └── c.h
│ │ └── src
│ │ └── c.cpp
│ └── CMakeLists.txt
├── CMakeLists.txt
└── main.cpp
9 directories, 9 files
where a is your super project that contains other subprojects. The contents for the b and c libraries are as follows:
# a/b/CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project(b CXX)
add_library(b
include/b/b.h
src/b.cpp
)
add_library(b::b ALIAS b)
target_include_directories(b
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install(TARGETS
b
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
install(DIRECTORY include/b DESTINATION include)
/* a/b/include/b/b.h */
#ifdef __cplusplus
extern "C" {
#endif
double funcb(const double);
#ifdef __cplusplus
}
#endif
/* a/b/src/b.cpp */
#include "b/b.h"
extern "C" {
double funcb(const double x) { return x + x; }
}
# a/c/CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project(c CXX)
add_library(c
include/c/c.h
src/c.cpp
)
add_library(c::c ALIAS c)
target_include_directories(c
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install(TARGETS
c
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
install(DIRECTORY include/c DESTINATION include)
/* a/c/include/c/c.h */
#ifdef __cplusplus
extern "C" {
#endif
double funcc(const double);
#ifdef __cplusplus
}
#endif
/* a/c/src/c.cpp */
#include "c/c.h"
extern "C" {
double funcc(const double x) { return x * x; }
}
Then, you simply make a an INTERFACE library as follows:
# a/CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project(a)
add_subdirectory(b)
add_subdirectory(c)
add_library(a INTERFACE)
add_library(a::a ALIAS a)
target_link_libraries(a
INTERFACE
b::b
c::c
)
Finally, your application will be using the b and c libraries as usual:
#include <iostream>
using namespace std;
#include "b/b.h"
#include "c/c.h"
int main(int argc, char* argv[]) {
cout << funcb(5) << '\n';
cout << funcc(5) << '\n';
return 0;
}
and the corresponding CMakeLists.txt will read
cmake_minimum_required(VERSION 3.9)
project(app)
add_subdirectory(a)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE a::a)
I hope this solves your problem.
It will require you to change the directory structure. Header inclusion are tied to physical paths, and there are no physical path that resemble a/b/b.h. The solution will be to change the directory structure with something like this:
a
|-- CMakeLists.txt
|-- aConfig.cmake
`-- b
|-- CMakeLists.txt
|-- include
| `-- a
| `-- b
| `-- b.h
`-- src
`-- b.cpp
And set the target include directory to a/b/include

how to deal with the "fmt" golang library package for CLI testing

Disclaimer: I wish you a merry XMas and I hope my question does not disturb you!
sample.go:
package main
import(
"fmt"
"os"
)
type sample struct {
value int64
}
func (s sample) useful() {
if s.value == 0 {
fmt.Println("Error: something is wrong!")
os.Exit(1)
} else {
fmt.Println("May the force be with you!")
}
}
func main() {
s := sample{42}
s.useful()
s.value = 0
s.useful()
}
// output:
// May the force be with you!
// Error: something is wrong!
// exit status 1
I did a lot of research on how to use interfaces in golang testing. But so far I was not able to wrap my head around this completely. At least I can not see how interfaces help me when I need to "mock" (apologies for using this word) golang std. library packages like "fmt".
I came up with two scenarios:
use os/exec to test the command line interface
wrap fmt package so I have control and am able to check the output strings
I do not like both scenarios:
I experience going through the actual command line a convoluted and not-performant (see below). Might have portability issues, too.
I believe this is the way to go but I fear that wrapping the fmt package might be a lot of work (at least wrapping the time package for testing turned out a non-trivial task (https://github.com/finklabs/ttime)).
Actual Question here: Is there another (better/simpler/idiomatic) way?
Note: I want to do this in pure golang, I am not interested in the next testing framework.
cli_test.go:
package main
import(
"os/exec"
"testing"
)
func TestCli(t *testing.T) {
out, err := exec.Command("go run sample.go").Output()
if err != nil {
t.Fatal(err)
}
if string(out) != "May the force be with you!\nError: this is broken and not useful!\nexit status 1" {
t.Fatal("There is something wrong with the CLI")
}
}
Chapter 11 of Kerningham's Book gives a good solution to this question.
The trick is to change the calls to fmt.Printline() to calls to
fmt.Fprint(out, ...) where out is initialised to os.Stdout
This can be overwritten in the test harness to new(bytes.Buffer) allowing the
test to capture the output.
See https://github.com/adonovan/gopl.io/blob/master/ch11/echo/echo.go and
https://github.com/adonovan/gopl.io/blob/master/ch11/echo/echo_test.go
edited by OP...
sample.go:
package main
import(
"fmt"
"os"
"io"
)
var out io.Writer = os.Stdout // modified during testing
var exit func(code int) = os.Exit
type sample struct {
value int64
}
func (s sample) useful() {
if s.value == 0 {
fmt.Fprint(out, "Error: something is wrong!\n")
exit(1)
} else {
fmt.Fprint(out, "May the force be with you!\n")
}
}
func main() {
s := sample{42}
s.useful()
s.value = 0
s.useful()
}
// output:
// May the force be with you!
// Error: this is broken and not useful!
// exit status 1
cli_test.go:
package main
import(
"bytes"
"testing"
)
func TestUsefulPositive(t *testing.T) {
bak := out
out = new(bytes.Buffer)
defer func() { out = bak }()
s := sample{42}
s.useful()
if out.(*bytes.Buffer).String() != "May the force be with you!\n" {
t.Fatal("There is something wrong with the CLI")
}
}
func TestUsefulNegative(t *testing.T) {
bak := out
out = new(bytes.Buffer)
defer func() { out = bak }()
code := 0
osexit := exit
exit = func(c int) { code = c }
defer func() { exit = osexit }()
s := sample{0}
s.useful()
if out.(*bytes.Buffer).String() != "Error: something is wrong!\n" {
t.Fatal("There is something wrong with the CLI")
}
if code != 1 {
t.Fatal("Wrong exit code!")
}
}
Am I missing something here or are you talking of testable examples?
Basically, it works like this: In a *_test.go file, you need to adhere to the convention Example[[T][_M]] where T is a placeholder for the type and M a placeholder for the method you want to display the testable example as example code in the Godoc. If the function is just called Example(), the code will be shown as a package example.
Below the last line of the code of your example, you can put a comment like this
// Output:
// Foo
Now go test will make sure that the testable example function either exactly puts out everything below // Output: (including whitespace) or it will make the test fail.
Here is an actual example for an testable example
func ExampleMongoStore_Get() {
sessionId := "ExampleGetSession"
data, err := ms.Get(sessionId)
if err == sessionmw.ErrSessionNotFound {
fmt.Printf("Session '%s' not found\n", sessionId)
data = make(map[string]interface{})
data["foo"] = "bar"
ms.Save(sessionId, data)
}
loaded, _ := ms.Get(sessionId)
fmt.Printf("Loaded value '%s' for key '%s' in session '%s'",
loaded["foo"],
"foo", sessionId)
// Output:
// Session 'ExampleGetSession' not found
// Loaded value 'bar' for key 'foo' in session 'ExampleGetSession'
}
Edit: Have a look at the output of above example at godoc.org

Go - how can i install selenium to use it in go language?

I am trying to run and test this code but the selenium is missing and i cant install it in my system, what should i do in that case please?
ERROR: while execute
test.go:8:2: import "bitbucket.org/tebeka/selenium": cannot find package
INSTALL the package i tried:
# apt-get install goisntall
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package goisntall
# apt-cache search goinstall
golang-src - Go programming language compiler - source files
CODE: testing
/* Selenium example goinstall bitbucket.org/tebeka/selenium */
package yahoo
import (
"strings"
"testing"
"bitbucket.org/tebeka/selenium"
)
func TestYahoo(t *testing.T) {
/* We want firefox, don't care about version much */
caps := selenium.Capabilities {
"browserName": "firefox",
}
wd, _ := selenium.NewRemote(caps, "", "")
defer wd.Quit()
/* Navigate to Yahoo */
wd.Get("http://www.yahoo.com")
/* Fill the search box */
input, err := wd.FindElement(selenium.ByName, "p")
if err != nil {
t.Error(err.String())
}
err = input.SendKeys("golang")
if err != nil {
t.Error(err.String())
}
/* Hit the search button */
button, err := wd.FindElement(selenium.ById, "search-submit")
if err != nil {
t.Error(err.String())
}
err = button.Click()
if err != nil {
t.Error(err.String())
}
/* See that we get expected result */
source, err := wd.PageSource()
if err != nil {
t.Error(err.String())
}
if !strings.Contains(source, "The Go Programming Language") {
t.Error("Google can't find Go")
}
}
For example, with GOPATH set appropriately,
$ env | grep '^GOPATH'
GOPATH=/home/peter/gopath
$ go get -v bitbucket.org/tebeka/selenium
bitbucket.org/tebeka/selenium (download)
bitbucket.org/tebeka/selenium
$
References:
Command go
Download and install packages and dependencies

How to read a binary file in Go

I'm completely new to Go and I'm trying to read a binary file, either byte by byte or several bytes at a time. The documentation doesn't help much and I cannot find any tutorial or simple example (by the way, how could Google give their language such an un-googlable name?). Basically, how can I open a file, then read some bytes into a buffer? Any suggestion?
For manipulating files, the os package is your friend:
f, err := os.Open("myfile")
if err != nil {
panic(err)
}
defer f.Close()
For more control over how the file is open, see os.OpenFile() instead (doc).
For reading files, there are many ways. The os.File type returned by os.Open (the f in the above example) implements the io.Reader interface (it has a Read() method with the right signature), it can be used directly to read some data in a buffer (a []byte) or it can also be wrapped in a buffered reader (type bufio.Reader).
Specifically for binary data, the encoding/binary package can be useful, to read a sequence of bytes into some typed structure of data. You can see an example in the Go doc here. The binary.Read() function can be used with the file read using the os.Open() function, since as I mentioned, it is a io.Reader.
And there's also the simple to use io/ioutil package, that allows you to read the whole file at once in a byte slice (ioutil.ReadFile(), which takes a file name, so you don't even have to open/close the file yourself), or ioutil.ReadAll() which takes a io.Reader and returns a slice of bytes containing the whole file. Here's the doc on ioutil.
Finally, as others mentioned, you can google about the Go language using "golang" and you should find all you need. The golang-nuts mailing list is also a great place to look for answers (make sure to search first before posting, a lot of stuff has already been answered). To look for third-party packages, check the godoc.org website.
HTH
This is what I use to read an entire binary file into memory
func RetrieveROM(filename string) ([]byte, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
stats, statsErr := file.Stat()
if statsErr != nil {
return nil, statsErr
}
var size int64 = stats.Size()
bytes := make([]byte, size)
bufr := bufio.NewReader(file)
_,err = bufr.Read(bytes)
return bytes, err
}
For example, to count the number of zero bytes in a file:
package main
import (
"fmt"
"io"
"os"
)
func main() {
f, err := os.Open("filename")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
data := make([]byte, 4096)
zeroes := 0
for {
data = data[:cap(data)]
n, err := f.Read(data)
if err != nil {
if err == io.EOF {
break
}
fmt.Println(err)
return
}
data = data[:n]
for _, b := range data {
if b == 0 {
zeroes++
}
}
}
fmt.Println("zeroes:", zeroes)
}
You can't whimsically cast primitive types to (char*) like in C, so for any sort of (de)serializing of binary data use the encoding/binary package.
http://golang.org/pkg/encoding/binary .
I can't improve on the examples there.
Here is an example using Read method:
package main
import (
"io"
"os"
)
func main() {
f, e := os.Open("a.go")
if e != nil {
panic(e)
}
defer f.Close()
for {
b := make([]byte, 10)
_, e = f.Read(b)
if e == io.EOF {
break
} else if e != nil {
panic(e)
}
// do something here
}
}
https://golang.org/pkg/os#File.Read