Taming the Visual Studio Code for Golang

There are few tips which I have collected over time when I was using Visual Studio Code for editing my Go code.

Using gogetdoc as the default documentation provider

Sometimes I came across a code which wasnt showing tooltips and over a function for me. To me it looks like godoc doesn’t handle well non local sources.

Luckily we can enable gogetdoc quite easily, just open Visual Studio Code, press Shift+Cmd+P (Shift+Alt+P) to open Command Palette and type in Open Settings (JSON), after hitting enter you will get VS’s settings.json opened. Find out if you have go.docsTool set and change it to gogetdoc like this:

"go.docsTool": "gogetdoc",
Screenshot 2019-05-27 at 20.48.29
Your tooltips should now work well.

Speed up the search in folder by keeping file cache alive

By default, simple search in workspace/folder is quite slow. It looks like editor is starting a special process just for search every time you start a new search. It is possible to keep the process in memory which makes search pretty fast. Open the Settings.json as in previous tip and set up:

"search.maintainFileSearchCache": true,

You can compare how fast it is when turned off. The keyboard shortcut to search is Shift+Cmd+F.

 

Enlarge the debugging tooltips for variable content

While debugging under Delve, the default limit used in VS is 64 characters, which is quite not enough. If you dont want to play with slices in debug window which also works.

Evaluating myvar[64:128] prints it

Without changes it looks somethings like this:

debugging-long-text.pngBut fortunatelly it is possible to edit your delve source code to increase limit as you want.

In the settings.json, place following configuration snippet

    "go.delveConfig": {
        "dlvLoadConfig": {
            "followPointers": true,
            "maxVariableRecurse": 1,
            "maxStringLen": 1000,
            "maxArrayValues": 1000,
            "maxStructFields": -1
        },
        "apiVersion": 2,
        "showGlobalVariables": true
    }
It increases the length of text nicely.
Btw. Did you know that there is Game of Thrones Lorem ipsum generator, for example here, the one by Rich Finelli.
The result can be observed here:
Screenshot 2019-05-28 at 20.21.08.png

Enabling the golang test log messages

Similarly like when running go test ./… any log messages produced by your tests like:

    t.Logf("logf Score %v\n", score)
    fmt.Printf("fmtf Score %v\n", score)

Are being ignored unless we start them with go test -v ./…
From those, fmt.Printf is printing immediatelly, while t.Logf waits until the test completes, so sometimes it might be more usefull to use fmt.Printf in tests.

Fortunatelly editor allows us to set up tests to use this argument. Open Settings.json again and write down:

"go.testFlags": ["-v"],
That will show the log messages the the Output window just right.

How to Import a GPX track to Garmin 920XT

I recently bought a Forerunner 920 and despite trying before my first cycling, I was unable to import a GPX file, which I created from a map, to navigate me on the road.

Now, several days later, I returned to the topic and I was hoping that I would get rid of my dependency on Phone because of map navigation. After another round of searching, I was much more successfull this time.

Thanks to Cyberbob99, here on Garmin Forums I found the way. The trick is that you have to have ..

gpsies.com to the rescue

Fortunatelly, there is a site www.gpsies.com, which can convert from a file, which misses route (connection among points), timing data, altitude, or otherwise not-complete Gpx file obtained by real excercise. Go there, register and by clicking Create/Upload load your Gpx data.

Then continue with just clicking download in the left-bottom side. You will get another Gpx file, this time it will be bigger, because it contains track and some made excercise.

www.gpsies.com before clicking download

Garmin Connect imports Gpx

With the newly obtained fully featured Gpx file, including some generated “cycling”, I am successfully able to import it to my online (modern) Garmin connect. I just need to add it as activity first, because courses do not have import.

In the Graphical menu, I choose Activity and Import (Gpx).

Importing new Activity, like if you exercised in real

 

The import should succeed and I got a new activity, happened sometimes in 2010 (I can remove it later).

Then I can go to the activity itself (should contain the map too) and I can click to small wheel in top-right. This expands a menu which has option to Save as Course.

 

We have a Course now

Now we can switch in Garmin connect to Courses, select the new one, we just created and when we go to its details, it should have option to Send to device. Click that option.

Sending course to the device

Now, it will ask you to Connect your device (I used Garmin Express, which needs to be installed on your Computer).

The rest is work of Garmin Express, Because I used Garmin Express, It asked me to connect device to Usb cradle, while page was searching for device, I set my device for sync and it was synchronised. I just returned to web and closed (still waiting) window on the site.

Then I went to my Garmin > Pressed three-dot button and went to Navigation > Tracks and the new map was there.

 

 

 

 

HTML 5 routing with Angular Cli on Ng server

If you are using Html 5 routing with old browsers (IE 11), probably you need special server side configuration (I am using this on IIS), . This article shows how to setup developer server routing in Angular Cli.

Using Angular Proxy to Backend

The Angular4 Cli is running on webpack dev server. Anyway Angular Cli natively supports only Proxy to backend configuration. It allows to setup which url pattern is being redirected internally by webserver. The configuration also allows to (redirect for example to localhost) and rewrite according to regex rules (provided by http=proxy=middleware module. The ng server needs configuration file, for example proxy.config.json and start ng serve with special parameter –proxy-config  to load configuration file.

The proxy.config.json file can look like this:

{
  "/": {
    "pathRewrite": {"^/(.+)": "/"},
    "target": "http://localhost:4200",
    "secure": false,
    "logLevel": "debug"
   }
}

The first line (with “/”) is asking to redirect all requests according to configuration in block.

The pathRewrite is doing to actual work. It changes url, which starts with / followed by some characters. The even better version could exclude strings with . (dot) like icon.gif from redirection, but this works well. Whatever is in form of slash and characters will be send to root “/” on server.

The target is the remote server, where your request is being proxied. It turns out this is required option. The original intent is to allow resending for example /api to another server. For our use we can use same server which ng server is hosting. In this case localhost.

To start ng server, with the config file use following argument:

ng serve --host localhost --proxy-config proxy.config.json --env dev --open

Common issues

If proxy doesnt work, verbose dev logging can be used to show redirections. Also, at the start lf ng serve, you should see two lines like:
[HPM] Proxy created: / -> http://localhost
[HPM] Proxy rewrite rule created: "^/(.+)" ~> "/"

Hopefully it helps.

Logging to a file with .NET Core

In the .net Core 1.0 the simple logging to a file is not included by default. I wanted to use the default logger infrastructure and also add support for TextWriterTraceListener. This article is showing how to do this.

Configuration in appsettings.json

The standard appsettings.json configuration file has Logging section, even with LogLevel subsection and looks like this:

"Logging": {
   "IncludeScopes": false,
   "LogLevel": {
   "Default": "Warning"
  }
 }
Let's reuse what we have and provide Log location here:
"LogFile": ".\\logs\\log.txt",

in the Application folder would need to be created logs folder. If you use IIS hosting with, you would need to add permissions to this folder for dynamic pool identity user.

The main configuration

In the Configure method, which is in Startup.cs, add these lines:

 

The AddTextWriter is adding TextWriter output to logger factory configuration – from the Configuration (appsettings.json). Then, we are creating concrete logger for this one class and log Info level message.

The AddTextWriter uses same Extensions based configuration style, so I have created ILoggerFactoryExtensions class to host them. Here is the whole class:

 

The AddTraceSource is reading from Configuration file, and tries to find full path to produced file – based on value in appsettings.json. Then creates new “old” TextWriterTraceListener, which passes as loggerFactory as new TraceSource

The loggerFactory’s AddTraceSource is only available if you add Nuget package “Microsoft.Extensions.Logging.TraceSource”.

The .net core LogLevel, used as level for TraceSource can have a bit different values, then SourceLevels enum, so I have simple conversion there.

The actual use is already shown in Configure method above. Once configured, its using standard .net core LoggerFactory, which can be injected in required methods.

Configuring EntityFramework for .NET Core

I will try to show some real example of .net core way of configuring Entity Framework Code First in this article. Microsoft documentation shows some examples, but the solution there creates one DbContext and stores it in DI container.

Downsize of that solution is that you cannot dispose container obtained from DI.

Better solution is to create a Factory class, store it as Singleton into Di container and create DbContext with this service.

public class MyDataContextFactory : IDataContextFactory
{
const string ConnectionStringName = "MyDbConn";
IConfigurationRoot configuration;
public DataContextFactory(IConfigurationRoot Configuration)
{
configuration = Configuration;
}
public DataContext Create()
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(
configuration.GetConnectionString(ConnectionStringName));
return new MyDataContext(optionsBuilder.Options);
}
}

Also, for this class, we would create interface IMyDataContextFactory, which will look like this:

public interface IMyDataContextFactory
{
MyDataContext Create();
}

The meat of this class is the method Create, which reads from Configuration the Db connection string and creates particular instance of DbContext. In my case called MyDataContext. I am passing Sql connection string read from configuration.

The class is taking IConfigurationRoot as only parameter, so that it could read from .Net Core Configuration. This is usually appsettings.json, but its up to your application.

Configuration and registration of the service

When you look to your Program.cs, you can see it configured like for example this:

public class Program
{
public static IConfigurationRoot Configuration { get; set; }
public static void Main(string[] args = null)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
/// and so on...

Please notice Configuration is – when created to class member.
The next step is to add Factory method to .Net core dependency injection container. In the Startup.cs file, locate your existing ConfigureServices, which is used for these things and add our line for example to end of it:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// Register MyDataContextFactory here
services.AddSingleton(
new DataContextFactory(Configuration));
}

How to use it in Controllers

The use is then similar to other Net Core DI services. We need to add our factory interface to particular Controller constructor, to get injected by DI automatically. It will look like this:

public class ValueController : Controller
{
private IMyDataContextFactory myDataContextFactory;
public ValueController(IMyDataContextFactory myDataContextFactory)
{
this.myDataContextFactory=myDataContextFactory;
}
// and so on

And use is then very simple, for example in same controller I can have method like:

public class ValueController : Controller
{
// ...
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(long id)
{
using (var context = dataContextFactory.Create())
{
var item = context.TodoItems.FirstOrDefault(t => t.Id == id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
// ...

So it is, hopefully this will help someone.

Thanks for reading.