I am working on connecting my application to MySql. The code is structured the following way, which works, but looks a little odd to me. Is this the right pattern to follow?
I have saved my Db related things in a separate file, which looks like this:
var DatabaseObject MySqlDatabase
type IMySqlDatabase interface {
ConnectToDb() MySqlDatabase
GetDb() MySqlDatabase
}
type MySqlDatabase struct{
Db *sql.DB
}
func (MySqlDatabase) ConnectToDb(connectionString string){
db, _ := sql.Open("mysql", connectionString)
_ = db.Ping()
DatabaseObject = MySqlDatabase{Db: db}
}
func (MySqlDatabase) GetDb() *sql.DB{
return DatabaseObject.Db
}
As such I can connect to the database the following way:
infrastructureMySql.DatabaseObject.ConnectToDb(connectionString)
Which I find odd. Is there any sense of having an interface in the first place? If I didn't have it I could simply use the *sql.DB as a global variable. Thank you for your feedback.
I generally like to follow this guide by Ben Johnson when creating db:
See 3. Wrap types for application-specific context
This article mentions that we can provide an abstract layer here by interacting with the interface and so you don't need to leak these details in the application layer.
You mentioned that you would like to perform queries and other commands so you can draw up an interface regarding those commands like so:
type Mysql struct {
db *sql.DB
}
// Wrap a new connection into the MySql struct
func NewMysql() (*Mysql, error) {
db, err := sql.Open(...)
return &Mysql{ db }, err
}
func (m *Mysql) GetUsers(...) ([]User, error) {}
func (m *Mysql) CreateUsers(...) (User, error) {}
type UserStore interface {
GetUsers func(...) []User, error)
CreateUsers func(...) (User, error)
}
This is definitely incorrect:
MySqlDatabase does not implement IMySqlDatabase, so it would not work if you actually tried to use the interface
You're not actually using the interface
And has style issues:
The interface returns concrete types, which defeats the purpose
The interface appears to be a factory of itself? Or something? It's unclear what the interface or the concrete type are really supposed to be/do
Interfaces in Go should not be named IThing, that's C#
You appear to have type methods which modify globals which is going to be extremely unexpected to anyone using them
Related
I want to test whether newrelic.NewConfig and newrelic.NewApplication are being called in the main() function.
import (
"github.com/newrelic/go-agent"
)
func main() {
/* NewRelic configuration */
newRelicConfig := newrelic.NewConfig("my-app-name",
os.Getenv("NEW_RELIC_LICENSE_KEY"))
app, err := newrelic.NewApplication(newRelicConfig)
// followed by other code
}
Should I move that code into a separate function within the main package, like:
func SetupNewRelicConfig() Application {
newRelicConfig := newrelic.NewConfig("my-app-name",
os.Getenv("NEW_RELIC_LICENSE_KEY"))
app, err := newrelic.NewApplication(newRelicConfig)
if err != nil {
log.Fatal(err)
}
return app
}
This way I can just check if the SetupNewRelicConfig is called or not.
What is the right way to test this?
Are you hoping to test this from an automated test, or as a runtime assertion of some type?
Assuming you're looking to add an automated test to your suite:
You need to find a way to mock the functions exported by the NewRelic package.
A very cheap way to do this is described here ("Monkey Patching in Golang"):
https://husobee.github.io/golang/testing/unit-test/2015/06/08/golang-unit-testing.html
A more comprehensive approach requires you to add these function calls to a struct that can be swapped by your test suite. See dependency injection, as described here:
https://medium.com/#zach_4342/dependency-injection-in-golang-e587c69478a8
Finally, look into using a mocking framework. I've had great luck with the mocking in stretchr's testify project.
I have a function which currently doesn't receive a bool parameter, but then calls another function with a hardcoded bool. We need to remove the hardcoded call and allow a bool to be passed.
I first thought I could try some default parameter - my google searches resulted in that Go apparently doesn't support optional (resp. default) parameter.
So I thought I'd try function overloading.
I found this thread on reddit, which says that it works with a special directive since version 1.7.3:
https://www.reddit.com/r/golang/comments/5c57kg/when_did_function_overloading_get_slipped_in/
I am using 1.8, and still I couldn't get it to work.
I am not even sure I may be allowed to use that directive, but I was speculating that changing the function signature right away may be dangerous as I don't know who uses the function...
Anyway - even with //+overloaded it didn't work
Is there any "idiosyncratic" way or pattern to solve this problem in Go?
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
//result, err := anotherFunc(rpath, true)
return self.Apply(rpath, lpath, true)
}
When I run my test, I get (forgive me for omitting part of the real path to file):
too many arguments in call to self.Apply
have (string, string, bool)
want (string, string)
../remotesystem.go:178: (*RemoteSystem).Apply redeclared in this block
previous declaration at ../remotesystem.go:185
Overloading isn't available in Go. Instead of writing functions with the same name that do different things, it is preferable to be more expressive with what the function does in the function name. In this instance, what would commonly be done is something like this:
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
func (self *RemoteSystem) ApplyDynamic(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
return self.Apply(rpath, lpath, true)
}
Just by the name of the function, you can easily tell what is different and why.
Another example to provide some context (pun intended).
I write a lot of Google App Engine code in Go using go-endpoints. The way to log things is different depending on if you have a context or not. My logging functions ended up like this.
func LogViaContext(c context.Context, m string, v ...interface{}) {
if c != nil {
appenginelog.Debugf(c, m, v...)
}
}
func LogViaRequest(r *http.Request, m string, v ...interface{}) {
if r != nil {
c := appengine.NewContext(r)
LogViaContext(c, m, v...)
}
}
From the Reddit post:
Unicode. I can tell by the pixels.
Go doesn't support function overloading. But it does support using Unicode characters in function names, which allows you to write function names that look like other function names.
The first one is setValue, the second one is setV\u0430lue aka setV\xd0\xb0lue (with CYRILLIC SMALL LETTER A) and the third is setVal\U0001d69ee aka setVal\xf0\x9d\x9a\x9ee (with MATHEMATICAL MONOSPACE SMALL U).
See also:
Does the Go language have function/method overloading? (stackoverflow.com)
Why does Go not support overloading of methods and operators? (golang.org)
Alternative for function overloading in Go? (stackoverflow.com)
XCTest test functions was called in alphabetical order (before Xcode 8). With Xcode 8, I can not assume in which order the test cases are called by the system.
Can someone throw light on it?
Tests within a class are run in a random order in Xcode 8. This encourages tests to be independent and repeatable.
I'm assuming that you want to run your tests in a specific order because they "chain" off of each other. For example, test_A logs a fake user in and test_B adds an item to the shopping cart. These type of tests should be avoided because they depend too much on each other. What if you want to run test_F alone? You shouldn't have to run A through E just to validate that F still works. Also, you could be introducing test pollution that is affecting other tests in ways you aren't yet aware of.
That said, having common or shared behavior between tests is fine, even ecouraged. You can put this login in the setUp method or extract private helper methods to handle specific events. For example, here's a very high-level example.
class AppTests: XCTestCase {
let subject = ViewController()
func setUp() {
super.setUp()
login(email: "user#example.com", password: "password")
}
func test_AddingItemsToCart() {
addItemToCart(21)
XCTAssertEqual(subject.itemsInCartLabel.text, "1")
}
func test_Checkout() {
addItemToCart(15)
checkout()
XCTAssertEqual(subject.totalPriceLabel.text, "$21")
}
private func login(email: String, password: String) { ... }
private func addItemToCart(item: Int) { ... }
private func checkout() { ... }
}
package main
import(
"fmt"
)
type A func (int,int)
func (this A) Serve() {
fmt.Println("function 1")
}
func Serve(int,int) {
fmt.Println("function 2")
}
func main() {
a := A(Serve)
a.Serve() // function 1
}
Function Serve can be converted to type A,which is also a function,but,I just don't get the idea of when and why we should use this approach,to deal with what kind of problem should we convert a function type to another?My example seems to be meaningless.
int,struct etc. are types,and what exactly is the function type different from the common known types like int and struct,from the underlying data structure perspective of view?
Thanks a lot!
It's a bit confusing indeed. I've seen this technique used to make an ordinary function compliant with an interface without the hassle of creating a struct and making the function a method of this struct - or other similar techniques.
A great example can be found in the standard http library. you have the type
type HandlerFunc func(ResponseWriter, *Request)
And it has the method:
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
This allows it to be used as the http.Handler interface which looks like this:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
This allows you to call http.ListenAndServe on an ordinary function without using the default http mux. wrapping the function as an http.Handler allows you to create a "mux-less" server.
Thus you can do something like:
http.ListenAndServe(":8080",
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//la di da
})
)
I am new to Go and am unsure about how to approach this problem. In OOP terms, I have a base class of Animal and two subclasses of Cat and Dog. I want to specify a ToJson method for Animal which will work for all animals.
My problem is that when I call dog.ToJson() I only get the Dog properties of dog and none of the Animal properties.
How can I make ToJson work as expected (ie with recursion)?
edit: Changed code to reflect suggestions in answer by lbonn, which I could not get to work how I want it to.
edit2: consistency in question following code change
package main
import (
"encoding/json"
"fmt"
)
type Animal struct {
Name string
}
type Cat struct {
CatProperty int64
Animal
}
type Dog struct {
DogProperty int64
Animal
}
func ToJson(i interface{}) []byte {
data,err := json.Marshal(i)
if err != nil {
panic("???")
}
return data
}
func main() {
dog := Dog{}
dog.Name = "rex"
dog.DogProperty = 2
fmt.Println(string(ToJson(dog)))
// Prints {"DogProperty":2}
// I want it to print {"Name":"rex","DogProperty":2}
}
Json encoding of anonymous fields was dropped from go 1. Hopefully it will be back in go 1.1. See https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/jYMHbEv44r4 for more details.
So the best you can get with the standard library right now (with go 1) is http://play.golang.org/p/LncNFeN8ys
You can always use skelterjohn's patch https://github.com/skelterjohn/json/ to support anonymous fields till go 1.1 is released.
Or use tip, installing from source that has this issue fixed. see https://codereview.appspot.com/6460044
Here, the ToJson method applies to the anonymous field Animal of Dog. The call d.ToJson is only a visibility shortcut to d.Animal.ToJson.
GoLang Tutorials: Anonymous fields in struct
Here, I would write a function instead of a method (a simple wrapper around Marshal):
func ToJson(i interface{}) []byte {
data,err := json.Marshal(i)
if err != nil {
panic("???")
}
return data
}
This is not specific to animals or dogs but it doesn't really need to.
More generally, there is no real notion of inheritance in go. The object paradigm used in the language is quite different from mainstream OOP, like in Java or C++. The Go FAQ provides some good clarifications about it.