Suppose I’m building a web app in Go. In my app, I want to send a message to my users. I can send a message to the users via email or SMS. This would be a perfect use case for interfaces.
For this hypothetical web app, I create the following main.go file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
package main
import"fmt"
type User struct { Name string Email string }
type UserNotifier interface { SendMessage(user *User, message string) error }
funcmain() { user := &User{"Dirk", "dirk@email.com"}
fmt.Printf("Welcome %s\n", user.Name) }
The User struct represents a user. You can see I created a UserNotifier of type interface that has a single function: SendMessage(). To implement this interface, I have to create a struct that implements the SendMessage() function.
As you can see, I created a new EmailNotifier struct. Then I implemented the SendMessage() method on the struct. Note that in this example, the EmailNotifier simply prints a message. In the real world, you would probably call an email API such as Mailgun.
And that’s it, the interface is now implemented.
The next thing to do is send an email to the user using the UserNotifier interface.
1 2 3 4 5 6 7 8
funcmain() { user := User{"Dirk", "dirk@email.com"} fmt.Printf("Welcome %s\n", user.Name)
var userNotifier UserNotifier userNotifier = EmailNotifier{} userNotifier.SendMessage(&user, "Interfaces all the way!") }
When running this program, the SendMessage() of the EmailNotifier is called correctly.
1 2 3 4
go build -o main main.go ./main Welcome Dirk Sending email to Dirk with content Interfaces all the way!
I’m a big fan of the Chrome Extension API. It is a simple (and cool) way to extend my favorite browser using HTML and JavaScript. One of the features I’ve been excited about for a while now is the DevTools API. This has been in “experimental” status for a while but is now (mostly) available in the main release.
The DevTools API allows you to integrate extensions directly into your DevTools. There are multiple samples of this API. But there aren’t any samples that detail how to create panels. There is documentation for creating panels, but it wasn’t clear how to use that API in a real extension. I dug at it for a while and finally figured it out. What follows is what I had to do to make panel creation work. It may not be the right way, but it worked. First, you must set a devtools_page value in your manifest.json. Here is my sample manifest.
Not much, right? As far as I can tell, the actual HTML for this file is never going to be rendered - anywhere. Instead, the entire point of this file is to load a JavaScript script. If so, it would be nice if Google would let us simply point devtools_page to a JavaScript script instead. Now let’s look at the script.
1 2 3 4 5
console.log("hello from devtools"); chrome.devtools.panels.create("ColdFire", "coldfusion10.png", "panel.html", function(panel) { console.log("hello from callback"); });
The main part of this script - for now - is just one line. It runs the panels.create API to define a new panel. The first argument is the title. The second is the icon. The third is the HTML file for the panel. Finally, the last argument is a callback to execute when the panel is created. There is no documentation on what size the icon should be. It seems to be 32x32.
Now let’s look at panel.html. I’ve only just begun development so for right now it is pretty simple.
And last but not least, the JavaScript file loaded by the panel:
1
console.log("panel.js");
So - what about all those console messages? As I tried to get things working, I used console messages all over the place so I could - hopefully - see what was going on. I had very little luck with this. I’ve blogged before about how to use console with Chrome Extensions, but that tip only works when you have a background script. My test extension did not. What finally worked was this:
Click the button that detaches Chrome Dev Tools With the Chrome Dev Tools in its own window and currently focused, use the keyboard combo to open Chrome Dev Tools This opens a second Chrome Dev Tools and I could see all my log messages there.
I hope this helps. As I said, I just got this working so I probably have a lot more to learn.
// Global, static list of items var itemList = []Item{ Item{Title: "Item A", Description: "The first item"}, Item{Title: "Item B", Description: "The second item"}, }
// Controller for the /items/{id} route funcreturnSingleItem(w http.ResponseWriter, r *http.Request) { // Get query parameters using Mux vars := mux.Vars(r)
// Convert {id} parameter from string to int key, err := strconv.Atoi(vars["id"])
// If {id} parameter is not valid int if err != nil { respondWithError(w, http.StatusBadRequest, "Invalid request payload") return }
// If Item with ID of {id} does not exist if key >= len(itemList) { respondWithError(w, http.StatusNotFound, "Item does not exist") return }
Mixed Content: The page at '<URL>' was loaded over HTTPS, but requested an insecure stylesheet '<URL>'. This request has been blocked; the content must be served over HTTPS.
https://laravel.com/docs/5.5/requests#configuring-trusted-proxies When running your applications behind a load balancer that terminates TLS / SSL certificates, you may notice your application sometimes does not generate HTTPS links. Typically this is because your application is being forwarded traffic from your load balancer on port 80 and does not know it should generate secure links.
funcfoo(w http.ResponseWriter, r *http.Request) { // Assuming you want to serve a photo at 'images/foo.png' fp := path.Join("images", "foo.png") http.ServeFile(w, r, fp) }
Important: http.ServeFile() does not automatically sanitize the file path. So if you’re constructing a file path from untrusted user input, you must sanitize the input with filepath.Clean() before using it to avoid directory traversal attacks.
Rendering a HTML Template
1 2 3 4
File: templates/index.html
<h1>Hello {{ .Name }}</h1> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
// Note that the layout file must be the first parameter in ParseFiles tmpl, err := template.ParseFiles(lp, fp) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return }
sudo bt start sudo service ssh --full-restart sudo service nginx restart sudo service mysqld restart sudo service redis restart sudo service php-fpm-73 restart sudo service cron start sudo supervisord sudo supervisorctl start all # 运行bash.exe不退出 whiletrue do sleep 600 done
gives 249676, so just TWICE as the first code example.
A
Use chunkById() instead of chunk().
When updating or deleting records inside the chunk callback, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the chunked results.